Monad绑定坚持不同的类型?

Joh*_* Z. 2 monads haskell

为什么这不是正确的实施?

instance Monad Lock where
   (Working False x) >>= _ = Working False x
   (Working True  x) >>= f = f x
Run Code Online (Sandbox Code Playgroud)

GHC吐出的错误是关于刚性类型变量的错误:

• Couldn't match type ‘a’ with ‘b’
  ‘a’ is a rigid type variable bound by
    the type signature for:
      (>>=) :: forall a b. Lock a -> (a -> Lock b) -> Lock b
    at src/Computers.hs:32:22
  ‘b’ is a rigid type variable bound by
    the type signature for:
      (>>=) :: forall a b. Lock a -> (a -> Lock b) -> Lock b
    at src/Computers.hs:32:22
  Expected type: Lock b
    Actual type: Lock a
Run Code Online (Sandbox Code Playgroud)

我可能误解了错误,但是从我有限的理解,编译器实际上需要我吐出不同的参数化类型,而不是相同的类型.

我尝试添加一个不带类型参数的不同构造函数(并且仅为测试更改语义) - 然后它工作正常:

instance Monad Lock where
   Broken            >>= _ = Broken
   (Working False x) >>= _ = Broken
   (Working True  x) >>= f = f x 
Run Code Online (Sandbox Code Playgroud)

编辑:确实,Lock的定义是:

data Lock a = Working Bool a
Run Code Online (Sandbox Code Playgroud)

Dan*_*ner 5

我假设您的定义Lock如下:

data Lock a = Working Bool a
Run Code Online (Sandbox Code Playgroud)

现在,让我们来看看类型(>>=):

(>>=) :: Lock a -> (a -> Lock b) -> Lock b
Run Code Online (Sandbox Code Playgroud)

这里最重要的是,它的调用者(>>=)(而不是执行者),其就可以选择的值a和b; 例如,我可能会使用它,就好像它有类型:

(>>=) :: Lock Int -> (Int -> Lock Bool) -> Lock Bool
Run Code Online (Sandbox Code Playgroud)

现在很明显为什么你的实现是不正确的:in

Working False int >>= _ = Working False int
Run Code Online (Sandbox Code Playgroud)

你将返回一个Lock Int而不是一个Lock Bool.