Avant de Haskell 98, il y avait Haskell 1.0 à 1.4. Il est assez intéressant de voir le développement à travers les années, que des fonctionnalités ont été ajoutées pour les premières versions de standards de Haskell.
Par exemple, la notation a d'abord été standardisée par Haskell 1.3 (publié 1996-05-01). Dans l' Prelude
, nous trouvons les définitions suivantes (page 87):
-- Monadic classes
class Functor f where
map :: (a -> b) -> f a -> f b
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
m >> k = m >>= \_ -> k
class (Monad m) => MonadZero m where
zero :: m a
class (MonadZero m) => MonadPlus m where
(++) :: m a -> m a -> m a
Les mêmes définitions sont trouvés en Haskell 1.4. J'ai quelques problèmes avec ce (par exemple, l' MonadPlus
réforme n'est pas arrivé ici encore), mais dans l'ensemble, c'est une très belle définition.
C'est très différent de Haskell 98, où la définition suivante est trouvé:
-- Monadic classes
class Functor f where
fmap :: (a -> b) -> f a -> f b
class Monad m where
(>>=) :: m a -> (a -> m b) -> m b
(>>) :: m a -> m b -> m b
return :: a -> m a
fail :: String -> m a
-- Minimal complete definition:
-- (>>=), return
m >> k = m >>= \_ -> k
fail s = error s
C'est aussi la définition en Haskell 2010. J'ai les problèmes suivants avec cette définition:
-
MonadZero
etMonadPlus
sont partis. Ils étaient classes utiles. -
Dans le cas d'une correspondance de modèle de l'échec en notation...
- Haskell 1.3 utilisations
zero
. La Gauche Zéro s'applique la loi (zero >>= k = zero
), de sorte que vous savez ce qui est censé se produire. - Haskell 98
fail msg
oùmsg
est généré par le compilateur en cas de GHC. Tout peut arriver, aucune garantie à propos de sa sémantique. Par conséquent, il n'est pas beaucoup d'une fonction pour les utilisateurs. En conséquence, le comportement de mise en correspondance du modèle échecs en Haskell 98 do-la notation est imprévisible!
- Haskell 1.3 utilisations
Les noms sont moins générales (par exemple,
map
vsfmap
). Pas un gros problème, mais c'est une épine dans mon œil.
Dans l'ensemble, je pense que ces changements n'étaient pas pour le meilleur. En fait, je pense qu'ils ont été un pas en arrière à partir de Haskell 1.4. Pourquoi ces choses ont changé pour Haskell 98, et pourquoi de cette façon?
En aparté, je peux imaginer la suite des défenses:
-
"
fail
permet de localiser les erreurs." Seulement pour les programmeurs, et seulement au moment de l'exécution. L' (portables!) message d'erreur n'est pas exactement quelque chose que vous voulez analyser. Si vous tenez vraiment à ce sujet, vous devez suivre explicitement. Nous avons maintenantControl.Failure
de lafailure
paquet, qui fait un bien meilleur travail à ce (failure x
se comporte essentiellement commezero
). - "Un trop grand nombre de classes rend le développement et l'utilisation trop dur." Ayant trop peu de cours sauts de leurs lois, et ces lois sont tout aussi importantes que les types.
-
"Exemple restreint de fonctions sont plus faciles à apprendre." Alors pourquoi n'est-il pas un
SimplePrelude
au lieu de cela, avec la plupart des classes supprimées? C'est seulement un magique déclaration à l'écart pour les élèves, ils peuvent gérer que beaucoup. (Peut -{-# LANGUAGE RebindableSyntax #-}
est nécessaire, mais encore une fois, les étudiants sont très bon à copier-coller des trucs.) -
"L'Instance restreinte par les fonctions d'erreurs plus lisible." J'utilise
fmap
beaucoup plus souvent que l'map
, alors pourquoi ne pas l'map
etlistMap
à la place?