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!

Foi útil?

Solução

  1. o retorno deve ter tipo forall b. b -> Either a b, no entanto, a esquerda tem tipo forall c. a -> Either a c. Você provavelmente quer aqui.
  2. fail deve ter tipo forall b. String -> Either a b, no entanto, certo tem tipo forall b. b -> Either a b, então se b=String isto faz String -> Either a String que não se encaixa.
  3. >>= deve ter tipo Either a b -> (b -> Either a c) -> Either a c Contudo Right x >>= _ = Right x sempre retorna um valor do tipo Either a b, não Either a c.
  4. Left x >>= f = f x não funciona porque x tem tipo a, mas f tem tipo b -> 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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top