Est spécifique à la notation à faire « base: GHC.Base.Monad »?
Question
L'idée que la classe standard Monad
est erronée et qu'elle devrait étendre effectivement Functor
ou Pointed
est flottant autour.
Je ne prétends pas nécessairement qu'il est la bonne chose à faire, mais supposons que l'on essayait de le faire:
import Prelude hiding (Monad(..))
class Functor m => Monad m where
return :: a -> m a
join :: m (m a) -> m a
join = (>>= id)
(>>=) :: m a -> (a -> m b) -> m b
a >>= t = join (fmap t a)
(>>) :: m a -> m b -> m b
a >> b = a >>= const b
Jusqu'à présent, si bon, mais en essayant d'utiliser faire la notation:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
Le compilateur se plaint:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Question:
fonctionne-t-do-notation seulement pour base:GHC.Base.Monad
? Est-il un moyen de le faire fonctionner avec une classe Monad
alternative?
Contexte supplémentaire:
Ce que je veux vraiment faire est de remplacer base:Control.Arrow.Arrow
par un « généralisé » classe Arrow
:
{-# LANGUAGE TypeFamilies #-}
class Category a => Arrow a where
type Pair a :: * -> * -> *
arr :: (b -> c) -> a b c
first :: a b c -> a (Pair a b d) (Pair a c d)
second :: a b c -> a (Pair a d b) (Pair a d c)
(***) :: a b c -> a b' c' -> a (Pair a b b') (Pair a c c')
(&&&) :: a b c -> a b c' -> a b (Pair a c c')
Et puis utilisez proc notation du Arrow
avec ma classe Arrow
, mais qui ne parvient comme dans l'exemple ci-dessus do notation et Monad
.
Je vais utiliser la plupart du temps Either
comme mon constructeur de type paire et non le constructeur de type (,)
comme avec la classe actuelle de Arrow
. Cela pourrait permettre de rendre le code de mon jouet jeu RTS (de cabal install DefendTheKind
) beaucoup plus joli.
La solution
Vous devez utiliser le Extension NoImplicitPrelude syntaxe complète rebindable, y compris do
et proc
. Dans ce cas, vous obtenez ce qui suit, entre autres choses:
notation "Do" est traduit en utilisant quelles que soient les fonctions (>> =), (>>), et l'échec, sont une portée (pas les versions Prelude). Liste compréhensions, MDO (Section 7.3.6, « Le do-notation récursive ») et matrice parallèle compréhensions, ne sont pas affectés.
Vous pouvez également modifier une manipulation de la négation, l'égalité, les valeurs littérales, et ainsi de suite. Un excellent moyen de coder obfuscate!
p.s. - Si vous allez rebind la syntaxe do
, ce que monades des appels sigfpe « paramétrées « sont très amusant. La même idée est disponible en category-extras
sous Control.Monad.Indexed . Et oui, ils fonctionnent avec la syntaxe rebindable, malgré les signatures de type très différentes!