看似正确的类型签名在 where 块中被拒绝
Seemingly correct type signature refused in where block
我一直在研究 Haskell 中的延续传球风格。将 Cont
monad 分开并删除类型包装器有助于我理解实现。这是代码:
{-# LANGUAGE ScopedTypeVariables #-}
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
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 a = Cont ka'
where
-- ka' :: (a -> r) -> r
ka' ha = ha a
此代码编译(使用 GHC 8.0.2)并且一切正常。但是,一旦我取消注释 where 块中的任何(现在已注释的)类型签名,我就会收到错误消息。例如,如果我取消注释行
-- ka' :: (a -> r) -> r
我得到:
• Couldn't match type ‘a’ with ‘a1’
‘a’ is a rigid type variable bound by
the type signature for:
(>>=) :: forall a b. Cont r a -> (a -> Cont r b) -> Cont r b
at cont.hs:19:6
‘a1’ is a rigid type variable bound by
the type signature for:
ka' :: forall a1. (a1 -> r) -> r
at cont.hs:27:14
Expected type: (a1 -> r) -> r
Actual type: (a -> r) -> r
• In the expression: runCont ka
In an equation for ‘ka'’: ka' = runCont ka
In an equation for ‘>>=’:
ka >>= kab
= Cont kb'
where
kb' hb
= ka' ha
where
ha a = (kab' a) hb
ka' :: (a -> r) -> r
ka' = runCont ka
kab' a = runCont (kab a)
• Relevant bindings include
ka' :: (a1 -> r) -> r (bound at cont.hs:28:7)
kab' :: a -> (b -> r) -> r (bound at cont.hs:31:7)
kab :: a -> Cont r b (bound at cont.hs:19:10)
ka :: Cont r a (bound at cont.hs:19:3)
(>>=) :: Cont r a -> (a -> Cont r b) -> Cont r b
(bound at cont.hs:19:3)
Failed, modules loaded: none.
所以我尝试使用类型通配符让编译器告诉我应该放什么类型签名。因此,我尝试了以下签名:
ka' :: _
出现以下错误:
• Found type wildcard ‘_’ standing for ‘(a -> r) -> r’
Where: ‘r’ is a rigid type variable bound by
the instance declaration at cont.hs:15:10
‘a’ is a rigid type variable bound by
the type signature for:
(>>=) :: forall a b. Cont r a -> (a -> Cont r b) -> Cont r b
at cont.hs:19:6
To use the inferred type, enable PartialTypeSignatures
• In the type signature:
ka' :: _
In an equation for ‘>>=’:
ka >>= kab
= Cont kb'
where
kb' hb
= ka' ha
where
ha a = (kab' a) hb
ka' :: _
ka' = runCont ka
kab' a = runCont (kab a)
In the instance declaration for ‘Monad (Cont r)’
• Relevant bindings include
ka' :: (a -> r) -> r (bound at cont.hs:28:7)
kab' :: a -> (b -> r) -> r (bound at cont.hs:31:7)
kab :: a -> Cont r b (bound at cont.hs:19:10)
ka :: Cont r a (bound at cont.hs:19:3)
(>>=) :: Cont r a -> (a -> Cont r b) -> Cont r b
(bound at cont.hs:19:3)
Failed, modules loaded: none.
现在我真的很困惑,编译器告诉我 ka'
的类型是 (a -> r) -> r
但是当我尝试用这种类型显式注释 ka'
时,
编译失败。起初我以为我错过了 ScopedTypeVariables
但它似乎没有什么不同。
这是怎么回事?
编辑
这类似于问题“”,因为它需要显式 forall
来绑定类型变量。但是它不是重复的,因为这个问题的答案也需要 InstanceSigs
扩展名。
有道理。毕竟,那些 a
和 b
是从哪里来的?我们无法知道它们与 (>>=)
和 return
的多态性有关。不过,如评论中所述,修复起来很容易:给出 (>>=)
和 return
类型签名,其中提到 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
我觉得所有这些 ka
和 ha
中都有一个龙珠笑话,但笑话逃脱了 me
。
我一直在研究 Haskell 中的延续传球风格。将 Cont
monad 分开并删除类型包装器有助于我理解实现。这是代码:
{-# LANGUAGE ScopedTypeVariables #-}
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
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 a = Cont ka'
where
-- ka' :: (a -> r) -> r
ka' ha = ha a
此代码编译(使用 GHC 8.0.2)并且一切正常。但是,一旦我取消注释 where 块中的任何(现在已注释的)类型签名,我就会收到错误消息。例如,如果我取消注释行
-- ka' :: (a -> r) -> r
我得到:
• Couldn't match type ‘a’ with ‘a1’
‘a’ is a rigid type variable bound by
the type signature for:
(>>=) :: forall a b. Cont r a -> (a -> Cont r b) -> Cont r b
at cont.hs:19:6
‘a1’ is a rigid type variable bound by
the type signature for:
ka' :: forall a1. (a1 -> r) -> r
at cont.hs:27:14
Expected type: (a1 -> r) -> r
Actual type: (a -> r) -> r
• In the expression: runCont ka
In an equation for ‘ka'’: ka' = runCont ka
In an equation for ‘>>=’:
ka >>= kab
= Cont kb'
where
kb' hb
= ka' ha
where
ha a = (kab' a) hb
ka' :: (a -> r) -> r
ka' = runCont ka
kab' a = runCont (kab a)
• Relevant bindings include
ka' :: (a1 -> r) -> r (bound at cont.hs:28:7)
kab' :: a -> (b -> r) -> r (bound at cont.hs:31:7)
kab :: a -> Cont r b (bound at cont.hs:19:10)
ka :: Cont r a (bound at cont.hs:19:3)
(>>=) :: Cont r a -> (a -> Cont r b) -> Cont r b
(bound at cont.hs:19:3)
Failed, modules loaded: none.
所以我尝试使用类型通配符让编译器告诉我应该放什么类型签名。因此,我尝试了以下签名:
ka' :: _
出现以下错误:
• Found type wildcard ‘_’ standing for ‘(a -> r) -> r’
Where: ‘r’ is a rigid type variable bound by
the instance declaration at cont.hs:15:10
‘a’ is a rigid type variable bound by
the type signature for:
(>>=) :: forall a b. Cont r a -> (a -> Cont r b) -> Cont r b
at cont.hs:19:6
To use the inferred type, enable PartialTypeSignatures
• In the type signature:
ka' :: _
In an equation for ‘>>=’:
ka >>= kab
= Cont kb'
where
kb' hb
= ka' ha
where
ha a = (kab' a) hb
ka' :: _
ka' = runCont ka
kab' a = runCont (kab a)
In the instance declaration for ‘Monad (Cont r)’
• Relevant bindings include
ka' :: (a -> r) -> r (bound at cont.hs:28:7)
kab' :: a -> (b -> r) -> r (bound at cont.hs:31:7)
kab :: a -> Cont r b (bound at cont.hs:19:10)
ka :: Cont r a (bound at cont.hs:19:3)
(>>=) :: Cont r a -> (a -> Cont r b) -> Cont r b
(bound at cont.hs:19:3)
Failed, modules loaded: none.
现在我真的很困惑,编译器告诉我 ka'
的类型是 (a -> r) -> r
但是当我尝试用这种类型显式注释 ka'
时,
编译失败。起初我以为我错过了 ScopedTypeVariables
但它似乎没有什么不同。
这是怎么回事?
编辑
这类似于问题“forall
来绑定类型变量。但是它不是重复的,因为这个问题的答案也需要 InstanceSigs
扩展名。
有道理。毕竟,那些 a
和 b
是从哪里来的?我们无法知道它们与 (>>=)
和 return
的多态性有关。不过,如评论中所述,修复起来很容易:给出 (>>=)
和 return
类型签名,其中提到 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
我觉得所有这些 ka
和 ha
中都有一个龙珠笑话,但笑话逃脱了 me
。