Haskell 的类型签名 u f=f.f 比我想要的强

Haskell's type signature of u f=f.f is stronger than I would like

我写了下面这个简单的函数

u f=f.f

根据 ghci 这具有

的类型签名
u :: (b -> b) -> b -> b

但是那个类型签名太严格了。 Haskell 强制我们的输入为 (b -> b) 类型,但不一定需要如此。例如,函数 (:[]) 的类型签名为

(:[]) :: a -> [a]

它不是 (b -> b) 的形式(除非您允许无限类型),因此无法传递给 u。但是你可以用它自己组合 (:[])

g=(:[]).(:[])

这有效并且具有类型

(:[]).(:[]) :: a -> [[a]]

所以我原则上应该能够将其传递给 u

我尝试自己编写一个新的类型签名来替换生成的签名,但我想不出一种方法来表达函数的要求。我总是想出与编译器提供的相同类型签名。我们是否可以提供类型签名来削弱 u 以便可以将 (:[]) 之类的函数传递给它?

有很多不同的函数可以针对特定情况执行此操作,但 none 通常都可以。

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)

没有 Haskell 中最通用的类​​型,当 RankNTypes 正在播放时。正如 pigworker 所指出的,有些类型系统可以为 u 提供您想要的基本类型,但它们将类型系统扩展的方向与 Haskell 设计人员所关注的方向截然不同。