O Do-Notation é específico para "Base: ghc.base.monad"?
Pergunta
A ideia de que o padrão Monad
a classe é falha e que realmente deve se estender Functor
ou Pointed
está flutuando ao redor.
Não estou necessariamente afirmando que é a coisa certa a fazer, mas suponha que alguém estivesse tentando fazê -lo:
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
Até agora tudo bem, mas depois de tentar usar a notação:
whileM :: Monad m => m Bool -> m ()
whileM iteration = do
done <- iteration
if done
then return ()
else whileM iteration
O compilador reclama:
Could not deduce (base:GHC.Base.Monad m) from the context (Monad m)
Pergunta:
Faz notação funciona apenas para base:GHC.Base.Monad
? Existe uma maneira de fazê -lo funcionar com uma alternativa Monad
classe?
Contexto extra:
O que eu realmente quero fazer é substituir base:Control.Arrow.Arrow
com um "generalizado" Arrow
classe:
{-# 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 então use o Arrow
é o Notation com o meu Arrow
aula, mas isso falha como no exemplo acima da notificação e Monad
.
Vou usar principalmente Either
como meu construtor de tipo de par e não o (,)
Tipo construtor como no atual Arrow
classe. Isso pode permitir fazer o código do meu jogo RTS de brinquedo (cabal install DefendTheKind
) muito mais bonito.
Solução
Você precisa usar o Extensão noimplicitPrelude para sintaxe completa recondável, incluindo do
e proc
. Nesse caso, você recebe o seguinte, entre outras coisas:
A notação "faça" é traduzida usando quaisquer funções (>> =), (>>) e falha, estão em escopo (não as versões do prelúdio). As compreensões da lista, o MDO (Seção 7.3.6, “A noção recursiva”) e compreensões paralelas da matriz, não são afetadas.
Você também pode ajustar algum manuseio de negação, igualdade, valores literais e outros enfeites. Ótima maneira de ofuscar o código!
PS - Se você vai reembindicar o do
sintaxe, O que o SIGFPE chama de "Mônadas parametrizadas" são muito divertidos. A mesma ideia está disponível em category-extras
debaixo Control.monad.indexed. E sim, eles trabalham com sintaxe rebenável, apesar das assinaturas de tipo muito diferentes!