人们使用身份功能做什么?

Pyt*_*Nut 15 haskell functional-programming julia

例如,Haskell具有id功能,Julia具有该identity功能,并且SO上的许多问题处理身份功能.(我想在Python中你可以这样做lambda x:x)

我一直在试图想到这个功能的用例; 我失败了

身份功能的目的是什么,它的常见用例是什么?

Ørj*_*sen 18

请记住,在Haskell中,函数是第一类值,可以像其他值一样用作数据,并作为参数传递给其他函数.通常,您可以通过将其他函数相互应用来构建您真正想要使用的函数.偶尔你会发现你想要在一个地方使用的功能碰巧没有什么比这更复杂了id.

例如,这是一个否定列表的每个第二个元素的函数:

negateEverySecond = zipWith id (cycle [id, negate])
Run Code Online (Sandbox Code Playgroud)

  • 如果编写`($)`,第一次使用`id`可能更容易理解. (5认同)

Toi*_*son 11

在朱莉娅(标准库):快速的grep显示,目前最突出使用的identity功能是作为默认值by参数的各种排序有关的功能,如sort!,sort,issorted,等.

by参数允许指定一个函数来提取从每个对象排序键,从而使两个对象ab根据比较by(a) < by(b)而不是a < b.该identity函数是自然的默认值,因为它identity(a) < identity(b)是相同的a < b.

也有一些内部排序的代码,是特例,因为当byidentity,这应该让更高效的代码为常见的情况.


dfe*_*uer 7

id在构建功能时可以是一个很好的起点.例如,

foldl f init xs = foldr (\x r -> \acc -> r (f acc x)) id xs $ init
Run Code Online (Sandbox Code Playgroud)

chi提到

type K a = (a -> Int) -> Int
-- factorial, CPS
factCPS :: Int -> K Int
factCPS 0 k = k 1
factCPS n k = factCPS (n-1) (k . (*n))

-- factorial, plain
fact :: Int -> Int
fact n = factCPS n id
Run Code Online (Sandbox Code Playgroud)

这种方法实际上与我上面给出的例子密切相关; 在id中的定义foldl实际上只是使用延续.

fact q
  = foldl (*) 1 [1..q]
  = foldr (\x r -> \acc -> r (acc * x)) id (build
      (\c n -> if q<1
               then n
               else let go k | k <= q = k `c` go (k+1)
                             | otherwise = n
                    in go 1)) 1
  -- foldr/build
  = (if q < 1
     then id
     else let go k | k <= q = \acc -> go (k+1) (acc * k)
                   | otherwise = id = \acc -> acc
          in go 1) 1
  = (if q < 1
     then id
     else let go k acc | k <= q = go (k+1) (acc * k)
                       | otherwise = acc
          in go 1) 1
  = if q < 1
    then 1
    else let go k acc | k <= q = go (k+1) (acc*k)
                      | otherwise = acc
         in go 1 1
Run Code Online (Sandbox Code Playgroud)

  • 或者函数列表的组成:`foldr(.)id`. (2认同)

Arn*_*non 6

大多数情况下,您将使用它来返回函数中未更改的参数的确切值.例如,在maybe.

我看到的另一个例子是(id &&& id)- 即.将元素复制到元组中.

?> let l = [5,3,4,1]
?> map (id &&& id) l
[(5,5),(3,3),(4,4),(1,1)]
Run Code Online (Sandbox Code Playgroud)

  • 但是这比`map(\ x - >(x,x))l`更好吗?这只是在Haskell做事的规范方式吗? (2认同)
  • @PythonNut,随着我对高阶函数的熟悉程度越来越高,我注意到lambda只是比较麻烦.通过这种方法,我可以轻松地编写可组合的变体,例如`(id &&&)` - 类型为`(a - > b) - >(a - >(a,b))`的函数,修改函数以包含它结果中的论证. (2认同)