È fare notazione specifica per “base: GHC.Base.Monad”?
Domanda
L'idea che la classe Monad
standard viene viziata e che dovrebbe in realtà estendere Functor
o Pointed
è galleggianti intorno.
Non sto necessariamente sostenendo che è la cosa giusta da fare, ma supponiamo che si stava cercando di farlo:
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
Fin qui tutto bene, ma poi quando si cerca di fare uso notazione:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
Il compilatore si lamenta:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Domanda:
fa fare notazione lavoro solo per base:GHC.Base.Monad
? C'è un modo per farlo funzionare con una classe Monad
alternativa?
contesto Extra:
Quello che voglio veramente fare è sostituire base:Control.Arrow.Arrow
con un "generalizzato" 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')
e quindi utilizzare proc notazione del Arrow
con la mia classe Arrow
, ma che non riesce, come nel precedente esempio di fai-notazione e Monad
.
Userò lo più Either
come il mio tipo di coppia di costruzione e non il tipo (,)
costruttore come con la classe Arrow
corrente. Ciò potrebbe consentire di rendere il codice del mio giocattolo gioco RTS (cabal install DefendTheKind
) molto più bella.
Soluzione
È necessario utilizzare il NoImplicitPrelude estensione per la piena sintassi rebindable, tra cui do
e proc
. In questo caso, si ottiene quanto segue, tra le altre cose:
notazione "Do" è tradotto usando qualsiasi funzione (>> =), (>>), e non riescono, sono di portata (non le versioni Prelude). list comprehension, MDO (Sezione 7.3.6, “Il ricorsiva do-la notazione”), e comprensioni di array paralleli, sono inalterati.
È anche possibile modificare alcuni trattamenti dei negazione, l'uguaglianza, valori letterali, e quant'altro. Ottimo modo per codice Oscurazione!
P.S. - Se avete intenzione di associare nuovamente la sintassi do
, quali chiamate SIGFPE "monadi parametrizzati " sono molto divertenti. La stessa idea è disponibile in category-extras
in Control.Monad.Indexed . E sì, lo fanno il lavoro con la sintassi rebindable, nonostante le selvaggiamente diverse firme di tipo!