【问题标题】:Higher order functions and id高阶函数和 id
【发布时间】:2018-03-14 20:55:32
【问题描述】:

我似乎无法理解id 是如何用作某些高阶函数的参数的。我在某处读到它用于“留下一些东西”,但似乎无法理解它。

比如liftA2 idf (b -> c) -> f b -> f c的类型为什么是这样的?

另外,为什么我不能将id 传递给g

g :: (Int -> Int -> Int) -> Int -> Int -> Int

?

【问题讨论】:

  • liftA2 idliftA2 ($) 的混淆版本。事实上,当id 被认为是一个二进制 函数时,最好写成($)

标签: haskell higher-order-functions


【解决方案1】:

我在某处读到 [id] 用于“不理会某事”,但我似乎无法理解它。

id 用于“不理会某事”,因为这就是它所做的一切——也就是说,什么都没有:

id :: x -> x
id x = x

既然如此,id 经常显示为传递给高阶函数的无操作占位符。 fmap id foo 实际上并没有改变在foo 中找到的值(实际上是fmap id = id,这是第一函子定律),id . ff . id 都等价于f,等等。一个更有趣的例子是the classic trick of defining foldl using foldr,其中id 用作使用foldr 构建函数的基本案例。

比如liftA2 idf (b -> c) -> f b -> f c的类型为什么是这样的?

liftA2 的类型是:

liftA2 :: (a -> b -> c) -> f a -> f b -> f c

对于liftA2 id,我们有...

(a -> (b -> c)) ~ (x -> x)

……等等……

a ~ x
(b -> c) ~ x

...因此...

liftA2 id :: f (b -> c) -> f b -> f c

(你可能知道,liftA2 id = (<*>)。如果你把它写成liftA2 ($)($) :: (a -> b) -> (a -> b) 只是一个专门的id,可能会更明显。)

另外,为什么我不能将id 传递给g

g :: (Int -> Int -> Int) -> Int -> Int -> Int

因为那样你就必须统一......

(Int -> (Int -> Int)) ~ (x -> x)

...这是不可能的,因为x 不能同时是IntInt -> Int

【讨论】:

  • 为了直观地理解“你必须统一......”,试试这个。 id 可以单独留下Int 并具有Int -> Int 类型(这与g 的参数具有相同的参数类型);或id 可以单独保留Int -> Int 函数并具有(Int -> Int) -> (Int -> Int) 又名(Int -> Int) -> Int -> Int 类型(这与g 的参数具有相同的结果类型)。但是,与人类不同的是,如果你试图单独留下两个 Ints,你不会在另一端只得到一个 Int,所以 id 不能有类型 Int -> Int -> Int
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-05-07
  • 2021-08-03
相关资源
最近更新 更多