我正在努力理解Haskell中函数签名类型中的函数, 我见过这个功能;
$('.photo-list').on('click', function (event) {
console.log("HELLO!");
});
在参数上选择的函数的两倍。我理解f是一个函数,但不明白为什么我们有签名类型twice :: (a -> a) -> a -> a
twice f x = f(f x)
我认为这将是(a -> a) -> a -> a
,因为
我是Haskell的新手:)
答案 0 :(得分:4)
让我们看看会发生什么!
twice :: (a -> b) -> a -> b
twice f x = f (f x)
只需阅读twice
的类型,我们立即知道:
f :: a -> b
x :: a
因此:
f x :: b
如果f :: a -> b
和f x :: b
,f (f x)
的类型是什么?我们不知道是否a = b
,因此我们不知道是否可以将f x
应用于f
。如果我们不知道那么我们就无法安全地编译该程序。
Couldn't match expected type `a' with actual type `b'
...
In the first argument of `f', namely `(f x)'
In the expression: f (f x)
答案 1 :(得分:0)
你是对的,函数的类型也可以用更通用的形式(a -> b) -> a -> b
来编写。但是,f (f x)
会出现轻微问题:f x
的结果为b
,但外f
期望其参数的类型为a
。因此a
和b
实际上必须是同一类型!你可以把它写成
twice :: (a~b) => (a -> b) -> a -> b
其中a~b
是等式约束(您需要其中一个GHC扩展TypeFamilies
或GATDs
,因此这是可接受的)。但如果两者都是相同的类型,你也可以立即给它们相同的名字......例如,a
。这简化了签名
twice :: (a -> a) -> a -> a