haskell - 为什么这个 Haskell 代码会编译?

标签 haskell

鉴于:

uncurry :: (a-> b -> c) -> (a,b) -> c    
id :: a -> a

调用 uncurry id产生一个函数类型:(b -> c, b) -> c
我们如何得到这个结果?

如何使用 id (a -> a) 作为 uncurry 的第一个参数,这需要 (a -> b -> c) 函数?

最佳答案

如果我们尝试从使类型解决的角度来看它更容易理解:弄清楚我们需要做什么到id的类型,使其适合 uncurry 所需的形状.因为我们有:

id :: a -> a

我们还有:
id :: (b -> c) -> (b -> c)

这可以通过替换 b -> c 来查看对于 aid 的原始类型中, 就像你可以替换 Int而是在确定 id 42 的类型时.然后我们可以去掉右边的括号,因为 (->)是右结合的:
id :: (b -> c) -> b -> c

显示 id的类型符合 a -> b -> c 的形式, 其中 ab -> c .换句话说,我们可以 reshape id的类型,只需专门化它已有的通用类型即可满足所需的形式。

理解这一点的另一种方法是查看 uncurry ($)也有类型 (b -> c, b) -> c .比较 id 的定义和 ($) :
id :: a -> a
id a = a

($) :: (a -> b) -> a -> b
($) f x = f x

我们可以使后一个定义更加无意义:
($) f = f

在这一点上,($)只是 id 的特化到更具体的类型变得清晰。

关于haskell - 为什么这个 Haskell 代码会编译?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8935568/

相关文章:

haskell - 是否可以在 Haskell 中编码一个通用的 "lift"函数?

haskell - 创建所有字段未定义的记录,不触发警告

haskell - 如何使用 HDBC 填写 SQL IN 占位符的参数?

haskell - 为什么使用在同一个模块中定义的函数比在另一个模块中定义的相同函数更快?

haskell - 如何通过 `cabal build` 或 `stack build` 构建带有图标的项目

haskell - 如何 "show"小写的构造函数

haskell - 如何找到最优的加工顺序?

postgresql - 使用 postgresql-simple 将 Postgres 间隔转换为 Haskell NominalTimeDiff

haskell - 一类改变类型的替换

haskell - cabal 使用(Haskell)