2010-04-06 30 views
5
instance Monad (Either a) where 
    return = Left 
    fail = Right 
    Left x >>= f = f x 
    Right x >>= _ = Right x 

este código de fragmentación en baby.hs '' causó la horrible error de compilación:¿Por qué este código de Either-monad no escribe check?

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 compilara este código? gracias por cualquier ayuda ~

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

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

compila con éxito! pero ... por un nuevo pregunta más:

instance Monad (Either a) 

hace 'O bien una' una mónada y yo nos 'retorno = Derecha' ... cómo podría conseguir 'retorno = Izquierda'? He intentado esto, pero fracasaron:

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

o: ejemplo Mónada (\ x -> O x a)

no compila en absoluto!

+0

Una publicación de blog sobre esto: http://ro-che.blogspot.com/2008/09/haskell-puzzle-either-monad.html –

Respuesta

3
  1. return debería tener el tipo forall b. b -> Either a b, sin embargo, Left tiene el tipo forall c. a -> Either a c. Probablemente quieras Aquí mismo.
  2. fail debe tener forall b. String -> Either a b tipo, sin embargo en este tipo tiene forall b. b -> Either a b, por lo que si b=String que hace String -> Either a String que no encaja.
  3. >>= debe 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 el tipo a, pero f tiene el tipo b -> c.
9

La mayor parte de la confusión proviene del hecho de que la izquierda y la derecha se usan al revés. Teniendo en cuenta sólo el tipo de retorno, su tipo de la clase de tipos mónada es el siguiente:

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

Usted está tratando de definir una instancia de m = Either a, por lo que el retorno debe tener Tipo:

return :: b -> Either a b 

se está definiendo como izquierda, que tiene tipo:

Left :: a -> Either a b 

Nota cómo el lado izquierdo de las -> difiere.

+0

veo.y ajusté el código para ver que compila: ejemplo Mónada (Ya sea a) cuando retorno = Derecha Izquierda un >> = f = Izquierda Derecha x un >> = f = f x compila correctamente! pero ... para una pregunta más adicional: instancia Monad (O bien uno) hace 'O bien una' mónada y tengo 'return = Right' ... ¿cómo podría obtener 'return = Left'? He intentado esto, pero fracasaron: ejemplo Mónada ('Either' a) cuando retorno = Izquierda Derecha un >> = f = Derecha Izquierda un x >> = f = fx o: ejemplo Mónada (\ x -> O bien xa) no compila en absoluto! –

+0

No se puede hacer que 'O a a' sea Monad con 'return' =' Left'. Una Haskell 'Monad' es una clase de tipo de un parámetro (tomemos' b'), que coincide con el tipo del argumento 'return'. Esto es incompatible con la definición de Haskell de 'Oither', que es una clase de tipo donde el último argumento es el de' Right '. Solo podría lograr lo que desea redefiniendo 'Oither' con argumentos de tipo intercambiado, como en' data O a b = Left b | Correcto a ', pero entonces sería incompatible con todo el soporte de la biblioteca estándar en' O bien 'valores. –

Cuestiones relacionadas