Por que esse código de qualquer um não digita verificação?
Pergunta
instance Monad (Either a) where
return = Left
fail = Right
Left x >>= f = f x
Right x >>= _ = Right x
Este código se fragmento em 'Baby.hs' causou o horrível erro de compilação:
Prelude> :l baby
[1 of 1] Compiling Main ( baby.hs, interpreted )
baby.hs:2:18:
Couldn't match expected type `a1' against inferred type `a'
`a1' is a rigid type variable bound by
the type signature for `return' at <no location info>
`a' is a rigid type variable bound by
the instance declaration at baby.hs:1:23
In the expression: Left
In the definition of `return': return = Left
In the instance declaration for `Monad (Either a)'
baby.hs:3:16:
Couldn't match expected type `[Char]' against inferred type `a1'
`a1' is a rigid type variable bound by
the type signature for `fail' at <no location info>
Expected type: String
Inferred type: a1
In the expression: Right
In the definition of `fail': fail = Right
baby.hs:4:26:
Couldn't match expected type `a1' against inferred type `a'
`a1' is a rigid type variable bound by
the type signature for `>>=' at <no location info>
`a' is a rigid type variable bound by
the instance declaration at baby.hs:1:23
In the first argument of `f', namely `x'
In the expression: f x
In the definition of `>>=': Left x >>= f = f x
baby.hs:5:31:
Couldn't match expected type `b' against inferred type `a'
`b' is a rigid type variable bound by
the type signature for `>>=' at <no location info>
`a' is a rigid type variable bound by
the instance declaration at baby.hs:1:23
In the first argument of `Right', namely `x'
In the expression: Right x
In the definition of `>>=': Right x >>= _ = Right x
Failed, modules loaded: none.
Por que isso acontece? E como eu poderia fazer esse código compilar? Obrigado por qualquer ajuda ~
Entendo. E eu ajustei o código para vê -lo compilar:
instance Monad (Either a) where
return = Right
Left a >>= f = Left a
Right x >>= f = f x
Combila com sucesso! Mas ... para mais uma pergunta mais:
instance Monad (Either a)
Faz 'A' A 'A Mônada e eu recebi' Return = Right '... como eu poderia obter' Return = esquerda '? Eu tentei isso, mas falhei:
instance Monad (`Either` a) where
return = Left
Right a >>= f = Right a
Left x >>= f = f x
ou: Monad da instância ( x -> ou Xa)
Não é compilado!
Solução
- o retorno deve ter tipo
forall b. b -> Either a b
, no entanto, a esquerda tem tipoforall c. a -> Either a c
. Você provavelmente quer aqui. fail
deve ter tipoforall b. String -> Either a b
, no entanto, certo tem tipoforall b. b -> Either a b
, então seb=String
isto fazString -> Either a String
que não se encaixa.>>=
deve ter tipoEither a b -> (b -> Either a c) -> Either a c
ContudoRight x >>= _ = Right x
sempre retorna um valor do tipoEither a b
, nãoEither a c
.Left x >>= f = f x
não funciona porque x tem tipoa
, masf
tem tipob -> c
.
Outras dicas
A maior parte da confusão deriva do fato que a esquerda e a direita é usada para trás. Considerando apenas o tipo de devolução, seu tipo de Monad Typeclass é o seguinte:
return :: (Monad m) => b -> m b
Você está tentando definir uma instância para m
= Either a
, então o retorno deve ter tipo:
return :: b -> Either a b
Você está definindo como esquerda, que tem tipo:
Left :: a -> Either a b
Observe como o lado esquerdo do ->
difere.