Haskell 在where块中拒绝看似正确的类型签名

Haskell 在where块中拒绝看似正确的类型签名,haskell,ghc,Haskell,Ghc,我在哈斯凯尔的传球风格上一直很混乱。拆下Contmonad并移除类型包装器有助于我理解实现。代码如下: {-#语言范围的TypeVariables} 进口管制.单子(ap) newtype Cont r a=Cont{runCont::(a->r)->r} 实例函子(续),其中 fmap f ka=ka>>=纯。F 实例应用程序(续),其中 ()=ap 纯=返回 实例Monad(续)其中 ka>>=kab=Cont kb' 哪里 --kb':(b->r)->r kb'hb=ka'ha 哪里 --

我在哈斯凯尔的传球风格上一直很混乱。拆下
Cont
monad并移除类型包装器有助于我理解实现。代码如下:

{-#语言范围的TypeVariables}
进口管制.单子(ap)
newtype Cont r a=Cont{runCont::(a->r)->r}
实例函子(续),其中
fmap f ka=ka>>=纯。F
实例应用程序(续),其中
()=ap
纯=返回
实例Monad(续)其中
ka>>=kab=Cont kb'
哪里
--kb':(b->r)->r
kb'hb=ka'ha
哪里
--ha::(a->r)
ha a=(kab'a)hb
--ka':(a->r)->r
ka'=runCont ka
--kab'::a->(b->r)->r
kab'a=运行控制(kab a)
返回a=Cont ka'
哪里
--ka':(a->r)->r
哈哈
这段代码经过编译(使用GHC 8.0.2),看起来一切正常。但是,一旦我取消注释where块中的任何(现在已注释)类型签名,我就会得到一个错误。例如,如果我取消注释该行

--ka':(a->r)->r
我得到:

•无法将类型“a”与“a1”匹配
“a”是一个刚性类型变量,由
以下项的类型签名:
(>>=)::对于所有a b。续a->(a->续b)->续b
续:19:6
“a1”是一个刚性类型变量,由
以下项的类型签名:
ka'::对于所有a1。(a1->r)->r
续:27:14
预期类型:(a1->r)->r
实际类型:(a->r)->r
•在表达式中:runCont ka
在“ka”的方程式中:ka'=runCont ka
在“>>=”的方程式中:
ka>>=kab
=续kb'
哪里
kb'血红蛋白
=嘉哈
哪里
ha a=(kab'a)hb
ka':(a->r)->r
ka'=runCont ka
kab'a=运行控制(kab a)
•相关绑定包括
ka':(a1->r)->r(在cont.hs:28:7处绑定)
kab'::a->(b->r)->r(在cont.hs:31:7处绑定)
kab::a->Cont r b(在Cont.hs:19:10绑定)
ka::Cont r a(在Cont.hs:19:3处绑定)
(>>=)::继续a->(a->继续b)->继续b
(续:19:3)
失败,已加载模块:无。
所以我尝试使用一个类型通配符,让编译器告诉我应该把什么类型的签名放在那里。因此,我尝试了以下签名:

ka'::_
这导致了以下错误:

•找到了类型通配符“34;代表“(a->r)->r”
其中:“r”是一个刚性类型变量,由
cont.hs:15:10的实例声明
“a”是一个刚性类型变量,由
以下项的类型签名:
(>>=)::对于所有a b。续a->(a->续b)->续b
续:19:6
要使用推断类型,请启用PartialTypeSignatures
•在类型签名中:
卡'::_
在“>>=”的方程式中:
ka>>=kab
=续kb'
哪里
kb'血红蛋白
=嘉哈
哪里
ha a=(kab'a)hb
卡'::_
ka'=runCont ka
kab'a=运行控制(kab a)
在“Monad(Cont r)”的实例声明中
•相关绑定包括
ka':(a->r)->r(在cont.hs:28:7处绑定)
kab'::a->(b->r)->r(在cont.hs:31:7处绑定)
kab::a->Cont r b(在Cont.hs:19:10绑定)
ka::Cont r a(在Cont.hs:19:3处绑定)
(>>=)::继续a->(a->继续b)->继续b
(续:19:3)
失败,已加载模块:无。
现在我真的很困惑,编译器告诉我
ka'
的类型是
(a->r)->r
,但是一旦我尝试用这种类型来明确地注释
ka'
, 编译失败。首先,我认为我缺少了
ScopedTypeVariables
,但这似乎没有什么区别

这是怎么回事

编辑
这与问题“”类似,因为它需要显式的
for all
来绑定类型变量。但是,它不是重复的,因为这个问题的答案还需要扩展名
InstanceSigs

是有意义的。毕竟,那些
a
s和
b
s来自哪里?我们无法知道它们与
(>>=)
返回的多态性有关。不过,正如注释中所述,修复起来很容易:给出
(>>=)
返回
类型签名,其中提到
a
b
,输入必要的语言扩展名,然后嘿,普雷斯托:

{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE InstanceSigs #-}

import Control.Monad (ap)


newtype Cont r a = Cont {runCont :: (a -> r) -> r}

instance Functor (Cont r) where
  fmap f ka = ka >>= pure . f

instance Applicative (Cont r) where
  (<*>) = ap
  pure = return

instance Monad (Cont r) where

  (>>=) :: forall a b. Cont r a -> (a -> Cont r b) -> Cont r b
  ka >>= kab = Cont kb'
    where
      kb' :: (b -> r) -> r
      kb' hb = ka' ha
        where
          ha :: (a -> r)
          ha a = (kab' a) hb

      ka' :: (a -> r) -> r
      ka' = runCont ka

      kab' :: a -> (b -> r) -> r
      kab' a = runCont (kab a)


  return :: forall a. a -> Cont r a
  return a = Cont ka'
    where
      ka' :: (a -> r) -> r
      ka' ha = ha a
{-#语言范围的TypeVariables}
{-#语言实例sigs}
进口管制.单子(ap)
newtype Cont r a=Cont{runCont::(a->r)->r}
实例函子(续),其中
fmap f ka=ka>>=纯。F
实例应用程序(续),其中
()=ap
纯=返回
实例Monad(续)其中
(>>=)::对于所有a b。续a->(a->续b)->续b
ka>>=kab=Cont kb'
哪里
kb':(b->r)->r
kb'hb=ka'ha
哪里
ha::(a->r)
ha a=(kab'a)hb
ka':(a->r)->r
ka'=runCont ka
kab'::a->(b->r)->r
kab'a=运行控制(kab a)
返回::对于所有a。a->Cont r a
返回a=Cont ka'
哪里
ka':(a->r)->r
哈哈

我觉得在所有这些
ka
s和
ha
s中都有一个龙珠笑话,但是这个笑话从
me
中逃脱了。毕竟,那些
a
s和
b
s来自哪里?我们无法知道它们与
(>>=)
r的多态性有关