"replace-if" 最好的方法是什么?

What is the best way to do "replace-if"?

我正在考虑一个函数,当 xy 时,可以将值 x 替换为 z,否则什么都不做,即:

\x -> if x == y then z else x

它只在我的程序中使用过一次,而且它在函数链的中间,所以我不想将它定义为命名函数,而且我认为 lambda 表达式看起来过于冗长。相反,我试图用其他函数来组合它。然而,到目前为止,我只想到了这个神秘的(和畏缩的)一个:

(ap . flip . bool id $ const z) (== y)

这么简单的函数有更好的无点形式吗?

我不是很赞成这个,但是一个快速的Hayoo search led me to the (?|) operator in the data-easy包。这个包充满了这样的功能(有一堆关于 "non-idiomatic haskell" 的免责声明)。看起来你可以

\x -> if x == y then z else x  -- the cluttered Haskell form

\x -> x ?| (/= y) $ z          -- the "Pythonic" form

(?| (/= y)) z                  -- Haskell-sections-galore of the "Pythonic" form

开个玩笑,还有更合理的 fromBoolC 你可能会喜欢:

fromBoolC z (/= y)

来自lens

import Control.Lens

f = (^. non z) . (non y # ) -- for some z and y

不过 if then else 版本肯定更好。

我不知道有什么可读性很强的东西。我能得到的最短的是

bool z <*> (/= y)

更多愚蠢的方法:

execState (gets (==y) >>= flip when (put z))

fromMaybe <*> flip lookup [(y, z)]

您可以使用 Python 技巧,用查找替换 case 语句。

import Data.Map

\x -> findWithDefault x x (singleton y z)

根据pointfree.io可以减少到

flip (join findWithDefault) (singleton y z)

不是很清楚,但同时它把函数部分和参数分开了。 flip (join findWithDefault) 做你想做的,singleton y z 是一种类似 DSL 的指定异常的方式。在你的代码前面加上 idExcept = flip (join findWithDefault)exception = singleton,你的链几乎是可读的。

my . awesome . (idExcept (exception y z)) . function . chain $ val