Qu'attendriez-vous d'une instance Alternative
pour vous donner. Je pense qu'une bonne façon pour vous d'avoir une idée de la façon dont Alternative
et Semigroup
diffèrent est de regarder un autre type qui a des cas pour les deux: par exemple Maybe String
:
λ > Just "a" <> Just "b"
Just "ab"
λ > Just "a" <> Nothing
Just "a"
λ > Nothing <> Just "b"
Just "b"
λ > Nothing <> Nothing
Nothing
λ > Just "a" <|> Just "b"
Just "a"
λ > Just "a" <|> Nothing
Just "a"
λ > Nothing <|> Just "b"
Just "b"
λ > Nothing <|> Nothing
Nothing
Bon, la principale différence semble être pour Just "a"
et Just "b"
. Cela est logique puisque vous les combinez dans le cas du Semigroup
plutôt que de prendre l'option biaisée de gauche dans le cas de Alternative
. Maintenant, pourquoi ne pas avoir une instance Alternative
pour Either
. Si vous regardez les fonctions qui font partie de la classe de type Alternative
:
λ > :i Alternative
class Applicative f => Alternative (f :: * -> *) where
empty :: f a
(<|>) :: f a -> f a -> f a
some :: f a -> f [a]
many :: f a -> f [a]
{-# MINIMAL empty, (<|>) #-}
On dirait qu'il définit une notion de empty
; c'est l'identité de l'opérateur (<|>)
. L'identité dans le cas signifie que l'alternative entre l'identité et quelque chose d'autre est toujours quelque chose d'autre.
Maintenant, comment construiriez-vous une identité pour Either e a
? Si vous observez la contrainte sur l'instance Alternative
, vous pouvez voir qu'il nécessite f
pour avoir une instance Applicative
. C'est bien, Either
a une instance Applicative
déclarée pour Either e
. Comme vous pouvez le voir le Either
est seulement un foncteur applicatif sur la deuxième variable de type (a
dans le cas de Either e a
). Donc, une identité pour Either e
aurait besoin de e
pour avoir aussi une identité. Bien qu'il soit possible de construire un type où e
a une instance de Alternative
vous ne pouvez pas créer une instance pour Alternative
pour Either
avec cette e
car aucune contrainte de ce type n'existe dans la définition de classe de type (quelque chose comme: (Alternative e, Applicative (f e)) => Alternative (f e)
).
TL; DR: Je suis désolé si je vous ai perdu avec mes divagations, court c'est que f
dans le cas de Either
est du mauvais genre, Alternative
nécessite f :: * -> *
tout Either
est de genreEither :: * -> * -> *
Ainsi Maybe
peut avoir une instance de Alternative
parce qu'il a typeMaybe : * -> *
et a une notion d'identité (Nothing
) qui est requis par empty
. Jetez un oeil à toutes les instances de Alternative
et faites attention au type de chaque type de données d'instance.
Vous pouvez trouver le type d'un type de données dans ghci avec :k
:
λ > :k Maybe
Maybe :: * -> *
λ > :k Either
Either :: * -> * -> *
Cela semble lié: https://ghc.haskell.org/trac/ghc/ticket/9588 –