Anu*_*ain 14 haskell existential-type
假设我有一个复合数据类型 -
data M o = M (String,o)
Run Code Online (Sandbox Code Playgroud)
现在,我可以定义一个适用于ALL的函数,M而不管它是什么o.例如 -
f :: M o -> M o
f (M (s,o)) = M (s++"!", o)
Run Code Online (Sandbox Code Playgroud)
然而,f并不像我希望的那样普遍.特别是,f在表达式中使用修复了类型,o所以我不能再使用f不同类型的o.例如,以下不是类型检查 -
p f = undefined where
m1 = M ("1", ())
m2 = M ("2", True)
m1' = f m1
m2' = f m2
Run Code Online (Sandbox Code Playgroud)
它产生错误 - Couldn't match expected type 'Bool' with actual type '()'
令人惊讶的是,如果我不提供f作为参数,而只是使用f的全局定义,那么它编译并正常工作!即编译 -
p = undefined where
m1 = M ("1", ())
m2 = M ("2", True)
m1' = f m1
m2' = f m2
Run Code Online (Sandbox Code Playgroud)
这有什么特别的原因吗?我如何解决这个问题,即定义一个f可以应用于所有的函数(M o),即使在o同一个表达式中变化?我猜测存在类型在这里发挥作用,但我无法弄清楚如何.
Sjo*_*her 15
问题是编译器无法正确推断p的类型.你必须给它一个类型签名:
p :: (forall o. M o -> M o) -> a
Run Code Online (Sandbox Code Playgroud)
这是排名2类型,因此您需要语言扩展名:
{-# LANGUAGE Rank2Types #-}
Run Code Online (Sandbox Code Playgroud)
要么
{-# LANGUAGE RankNTypes #-}
Run Code Online (Sandbox Code Playgroud)
在这里阅读更多相关信息:http://www.haskell.org/haskellwiki/Rank-N_types
这有什么特别的原因吗?
的确,有一个.用一句话来说:如果解除了HM系统的限制,那么类型推断将无法正常工作,因为lambda参数必须是单态的.
Simon Peyton Jones设计了一种类型检查器,它扩展了HM并允许更高级别的多态性.但在这种情况下,需要显式类型注释.见Sjoerds答案.
| 归档时间: |
|
| 查看次数: |
347 次 |
| 最近记录: |