Haskell中的隐性函数组合

Ben*_*ach 13 haskell function composition pointfree tacit-programming

假设我有一个mean如此定义的函数:

mean xs = sum xs / (fromIntegral $ length xs)
Run Code Online (Sandbox Code Playgroud)

但我想以某种默契形式,像这样:

mean = sum / (fromIntegral . length)
Run Code Online (Sandbox Code Playgroud)

是否有内置的Haskell方法可以在这些行中执行某些操作而无需构建自己的tacit函数(类似这样):

tacit :: (a -> b -> c) -> (d -> a) -> (d -> b) -> d -> c
tacit a b c i = a (b i) (c i)
Run Code Online (Sandbox Code Playgroud)

在这种形式中,函数如下所示:

mean = tacit (/) sum (fromIntegral . length)
Run Code Online (Sandbox Code Playgroud)

但感觉可能有一种方法可以避免使用像这样的显式函数.我是在想; 是否有一些方法可以做到内置于Haskell?

Art*_*yom 20

应用函子在这里工作得很好.

import Control.Applicative

mean = (/) <$> sum <*> (fromIntegral . length)
Run Code Online (Sandbox Code Playgroud)


huo*_*uon 14

是的,你的tacit函数liftM2(->) rmonad中(liftM2Control.Monad,并且Monad的函数实例在其中Control.Monad.Instances).

我发现这个使用该pointfree程序(你可以通过它安装cabal install pointfree),调用为:

$ pointfree '\xs -> sum xs / (fromIntegral $ length xs)'
Run Code Online (Sandbox Code Playgroud)

(在Unix终端中)

  • 然后你可以为`( - >)r`创建一个`Num`实例,然后`mean = sum /(fromIntegral.length)`实际上可以工作. (8认同)
  • @SjoerdVisscher:因为`(/)`你也需要`Fractional`.刚试了一下,确认了你所需要的一切. (5认同)
  • 另外一个有趣的补充是,一旦你有了'Num r => Num(a - > r)`实例,你可以添加自身:`(+)+(+)`成为一个类型很好的表达式(相当于`\ xy - >(x + y)+(x + y)`). (4认同)
  • @sacundim啊,对.而且"1 2 3 4"也是一个很好的表达方式.很清楚为什么这不是一个内置的实例. (3认同)
  • 嘿,我没想到那一个.但更糟糕的是,如果你的模块导入任何直接或间接使用此实例的模块,那么你将获得这个实例.所以应该用`newtype`来包装它 - 在这种情况下额外的语法开销意味着你也可以使用`Applicative`. (2认同)