Pregunta

instance Monad (Either a) where
     return = Left
     fail = Right
     Left x >>= f = f x
     Right x >>= _ = Right x

Este código se frag en 'baby.hs' causó el horrible error de compilación:

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 qué sucede esto? ¿Y cómo podría hacer que este código compile? Gracias por cualquier ayuda ~

veo. y ajusté el código para verlo compilación:

instance Monad (Either a) where
     return = Right
     Left a >>= f = Left a
     Right x >>= f = f x

¡Se compila con éxito! Pero ... para otra pregunta más:

instance Monad (Either a)

Hace que 'una' una mónada y obtuve 'return = right' ... ¿cómo podría obtener 'return = izquierda'? He intentado esto pero fallé:

instance Monad (`Either` a) where
     return = Left
     Right a >>= f = Right a
     Left x >>= f = f x

o: instancia monad ( x -> o xa)

¡No se compila en absoluto!

¿Fue útil?

Solución

  1. El regreso debe tener tipo forall b. b -> Either a b, sin embargo, la izquierda tiene tipo forall c. a -> Either a c. Probablemente quieras aquí.
  2. fail debería tener tipo forall b. String -> Either a b, sin embargo, el derecho tiene el tipo forall b. b -> Either a b, Así que si b=String lo que hace String -> Either a String que no encaja.
  3. >>= debería tener tipo Either a b -> (b -> Either a c) -> Either a c sin embargo Right x >>= _ = Right x siempre devuelve un valor de tipo Either a b, no Either a c.
  4. Left x >>= f = f x no funciona porque X tiene tipo a, pero f tiene tipo b -> c.

Otros consejos

La mayoría de la confusión proviene del hecho de que izquierda y derecha se usan hacia atrás. Teniendo en cuenta solo el tipo de retorno, su tipo de typeclass de mónadas es el siguiente:

return :: (Monad m) => b -> m b

Estás tratando de definir una instancia para m = Either a, así que la devolución debe tener tipo:

return :: b -> Either a b

Lo estás definiendo como a la izquierda, que tiene tipo:

Left :: a -> Either a b

Tenga en cuenta cómo el lado izquierdo del -> difiere.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top