我写了以下简单的函数
u f=f.f
根据ghci
,它具有
u :: (b -> b) -> b -> b
然而,该类型签名过于严格。 Haskell强制要求我们的输入属于(b -> b)
类型,而不一定需要它。例如,函数(:[])
的类型签名为
(:[]) :: a -> [a]
哪个不是(b -> b)
形式,(除非您允许无限类型),因此无法传递给u
。但是,您可以自己撰写(:[])
。
g=(:[]).(:[])
这样可以使用
类型(:[]).(:[]) :: a -> [[a]]
原则上,我应该将其传递给u
。
我试图自己编写一个新的签名来替换生成的签名,但我无法想出一种方法来表达函数的要求。我总是提出编译器提供的相同类型签名。我们可以提供类型签名来削弱u
,以便像(:[])
这样的函数可以传递给它吗?
答案 0 :(得分:17)
有许多不同的功能可以针对特定情况执行此操作,但通常无效。
u1 :: (forall a. a -> f a) -> b -> f (f b)
u2 :: (forall a. f a -> a) -> f (f b) -> b
并且可能无限多。但功能
u f x = f (f x)
当RankNTypes
正在播放时, 在Haskell中没有最常规的类型。正如Pigworker所指出的,有些类型系统可以为u
提供所需类型的主要类型,但它们将类型系统扩展与Haskell设计者关注的方向完全不同。