Ist do-Notation spezifisch für „base: GHC.Base.Monad“?
Frage
Die Idee, dass die Standard-Monad
Klasse fehlerhaft ist und dass es tatsächlich verlängern Functor
oder Pointed
schwimmt herum.
Ich behaupte nicht, dass es das Richtige ist, zu tun, sondern nehme an, dass man versuchte, es zu tun:
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
So weit so gut, aber dann, wenn zu verwenden do-Notation versuchen:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
Der Compiler beschwert sich:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Frage:
Does do-Notation Arbeit nur für base:GHC.Base.Monad
? Gibt es eine Möglichkeit, es funktioniert mit einer alternativen Monad
Klasse zu machen?
Extra-Kontext:
Was ich wirklich tun möchte, ist ersetzen base:Control.Arrow.Arrow
mit einer „generalisierten“ Arrow
Klasse:
{-# 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')
Und dann verwenden Sie die Arrow
der proc-Notation mit meiner Arrow
Klasse, aber das nicht wie im Beispiel oben von do-Notation und Monad
.
Ich werde meistens verwenden Either
als mein Paar Typkonstruktor und nicht die (,)
Typkonstruktor wie mit der aktuellen Arrow
Klasse. Dies könnte ermöglichen, den Code von meinem Spielzeug RTS-Spiel (cabal install DefendTheKind
) viel schöner zu machen.
Lösung
Sie müssen die NoImplicitPrelude Erweiterung für volle rebindable Syntax, einschließlich do
und proc
. In diesem Fall Sie die folgende erhalten, unter anderen Sachen:
"Do" Notation übersetzt mit unabhängig von Funktionen (>> =), (>>) und scheitert, ist in ihrem Umfang (nicht die Prelude-Versionen). Listenkomprehensionen, mdo (Abschnitt 7.3.6, „Die rekursive do-Notation“) und parallele Anordnung Comprehensions, sind nicht betroffen.
Sie können auch einig Umgang mit Negation zwicken, Gleichheit, Literalwerte, und so weiter. Große Weise zu verschleiern Code!
P. S. - Wenn Sie vorhaben, die do
Syntax, was SIGFPE Anrufe „parametrisierte Monaden erneut zu binden „ ist ein großer Spaß. Die gleiche Idee ist in category-extras
unter Control.Monad.Indexed . Und ja, sie funktionieren mit rebindable Syntax trotz der völlig unterschiedlichen Art Signaturen!