高阶函数和id

时间:2018-03-14 12:28:25

标签: haskell higher-order-functions

我似乎无法理解id如何用作某些高阶函数的参数。我曾经在某个地方读到过这样的习惯,就是单独留下一些东西"但似乎无法理解它。

例如,为什么liftA2 id f (b -> c) -> f b -> f c的类型?

另外,为什么我无法将id传递给g

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

1 个答案:

答案 0 :(得分:5)

  

我已经在某个地方读过[id]已经习惯了#34;留下一些东西"但似乎无法理解它。

id用于"留下一些东西"因为这就是它所做的一切 - 也就是说,没有:

id :: x -> x
id x = x

就是这样,id经常显示为传递给高阶函数的do-nothing占位符。 fmap id foo实际上并未更改foo内的值(事实上,fmap id = id,这是第一个仿函数法律),id . ff . id都等于f,等等。一个更有趣的示例是the classic trick of defining foldl using foldr,其中id用作构建foldr函数的基本案例。

  

例如,为什么liftA2 id f (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