Haskell函数用于反转函数调用

9

我有一个lambda表达式\x f -> f x,它被用在foldM操作中,其中x是一个值,f :: a -> b

是否有内置函数可以执行此操作?

我能否替换原来的lambda表达式?

foldM (\x f -> f x) ...

一些使用f'的技术

foldM f' ...

我原以为 flip 可以实现这个功能,但它需要三个参数 (flip :: (a -> b -> c) -> b -> a -> c)

这可能类似于 F# 中的 |>

2个回答

22
你可以使用flip idflip ($)(因为($)只是用于函数的特殊id):
Prelude> flip id 3 (+2)
5
Prelude> flip ($) 7 (>10)
False
这是partial application的一个有趣用法:id f x 中,f是一个函数,那么它就等同于 f x。显然,这也和 (flip id) x f 是相同的,所以flip id 就是你要找的函数。
如果你感到冒险,请尝试手动推断flip idflip ($) 的类型。很有趣 :)

1
哇,我用纸和笔大约花了5分钟才算出ida -> a签名如何映射到flip期望具有a -> b -> c的内容。也许值得深入探讨一下! - Asherah
1
@Len:当你看到id($)应用于函数时,它们的含义变得更清晰。 - Niklas B.
1
谢谢。Haskell 是一门很酷的编程语言,但我感觉我的大脑就像在一个迷宫里,到处都是相似的曲折小通道... - Ralph
2
@Ralph:在 Hackage 上也有 pointfree 包。使用 cabal install pointfreepointfree "\a b -> b a" 命令即可安装。 - Vitus
@Niklas B.:感谢您提供有趣的信息。现在我需要用纸和笔来工作。 - d12frosted
显示剩余4条评论

8
是的,这个函数叫做flip :: (a -> b -> c) -> b -> a -> c,例如:flip (>) 3 5 == True。更多信息和源码在 hackage 上: flip
你想做的就是简单地反转函数应用的参数吗?嗯,既然($)是函数应用,通过使用 flip,你可以编写flip ($) :: b -> (b -> c) -> c。让我们看看会发生什么。这里是两个预定义函数的源代码:
-- from Hackage:
($)                     :: (a -> b) -> a -> b
f $ x                   =  f x

-- from Hackage:
flip                    :: (a -> b -> c) -> b -> a -> c
flip f x y              =  f y x

基本上,如果您将类型组合在一起,flip ($) 就会变成

flip ($) :: 
  b        ->    -- type of x, argument of y and second argument of ($)
  (b -> c) ->    -- type of y, function applied by ($) as its first argument
  c        ->    -- result of the application "y x"

如果你遵循实际函数的定义:
flip ($) = (\f x y -> f y x) ($)    -- from flip's def.
         = \x y -> ($) y x          -- partial application
         = y x                      -- from ($)'s def.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接