为什么这个 Either-monad 代码不进行类型检查?

发布于 2024-08-27 11:45:50 字数 2418 浏览 10 评论 0原文

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

“baby.hs”中的这个代码片段导致了可怕的编译错误:

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.

为什么会发生这种情况?我怎样才能让这段代码编译? 谢谢你的帮助~

我明白了。我调整了代码以查看它的编译:

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

它编译成功! 但是......对于进一步的问题:

instance Monad (Either a)

使'Either a'成为单子并且我得到'return = Right'...我怎样才能得到'return = Left'? 我已经尝试过但失败了:

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

或者: instance Monad (\x -> Either xa)

根本无法编译!

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

this code frag in 'baby.hs' caused the horrible compilation error:

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.

why this happen? and how could I make this code compile ?
thanks for any help~

i see. and i adjusted the code to see it compiles:

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

it compiles successfully!
but...for a further more question:

instance Monad (Either a)

makes 'Either a' a monad and i got 'return = Right'...how could i get 'return = Left'?
i've tried this but failed:

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

or:
instance Monad (\x -> Either x a)

doesn't compile at all!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

深海蓝天 2024-09-03 11:45:50

大多数混乱源于“左”和“右”被反向使用的事实。仅考虑 return 的类型,它来自 Monad 类型类的类型如下:

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

您正在尝试为 m = Either a 定义一个实例,因此 return 应该具有类型:

return :: b -> Either a b

您将其定义为 Left,其类型为:

Left :: a -> Either a b

请注意 -> 左侧的不同之处。

Most of the confusion stems from the fact Left and Right are used backwards. Considering only the type for return, its type from the Monad typeclass is as follows:

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

You're trying to define an instance for m = Either a, so return should have type:

return :: b -> Either a b

You're defining it as Left, which has type:

Left :: a -> Either a b

Note how the left hand side of the -> differs.

星星的轨迹 2024-09-03 11:45:50
  1. 对于all b,返回值应具有类型。 b->要么是b,但Left 的类型是所有c。一个->要么是 c。您可能想要就在这里。
  2. fail 的类型应为 forall b。字符串 ->要么是b,但是Right 的类型是所有b。 b->要么是 b,所以如果 b=String 使得 String ->;要么是一个不适合的字符串。
  3. >>= 的类型应为 ab ->; (b -> 任一 ac) ->要么是 c,要么是 Right x >>>= _ = Right x 始终返回 Either a b 类型的值,而不是Either a c >。
  4. Left x >>= f = f x 不起作用,因为 x 的类型为 a,但 f 的类型为 b -> ; c.
  1. return should have type forall b. b -> Either a b, however Left has type forall c. a -> Either a c. You probably want Right here.
  2. fail should have type forall b. String -> Either a b, however Right has type forall b. b -> Either a b, so if b=String that makes String -> Either a String which does not fit.
  3. >>= should have type Either a b -> (b -> Either a c) -> Either a c however Right x >>= _ = Right x always returns a value of type Either a b, not Either a c.
  4. Left x >>= f = f x does not work because x has type a, but f has type b -> c.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文