【问题标题】:Pointfree (or library) function for applying two functions to single inputPointfree(或库)函数,用于将两个函数应用于单个输入
【发布时间】:2013-01-16 03:21:45
【问题描述】:

我一直在重复使用 lambda 表达式,例如

\x -> (f x, g x)

我将相同的输入应用于两个函数并将结果封装成一对。我可以写一个函数来捕捉这个

combine :: (a -> b) -> (a -> c) -> a -> (b,c)
combine f g x = (f x, g x)

现在上面的 lambda 表达式就是 combine f g。我有两个问题。

  1. 我很想知道是否有一个标准库函数可以执行此操作,但我找不到。
  2. 出于好奇,我想以无点样式重写此函数,但我遇到了很多麻烦。

【问题讨论】:

    标签: haskell pointfree


    【解决方案1】:
    1. Control.Arrow 为此具有函数(&&&)。它有一个“更通用”的类型,不幸的是,这意味着 Hoogle 没有找到它(也许这应该被认为是 Hoogle 中的一个错误?)。

    2. 您通常可以使用pointfree 自动计算出这类事情,#haskell 中的lambdabot 作为插件提供。

    例如:

    <shachaf> @pl combine f g x = (f x, g x)
    <lambdabot> combine = liftM2 (,)
    

    其中liftM2(r -&gt;) 实例Monad 的类型为(a -&gt; b -&gt; c) -&gt; (r -&gt; a) -&gt; (r -&gt; b) -&gt; r -&gt; c。当然,根据您允许的原语,还有许多其他方法可以编写这种无点。

    【讨论】:

    • 感谢您的简洁回答,感谢您将我指向 pointfree。
    【解决方案2】:

    我很想知道是否有一个标准库函数可以做到这一点,而我只是找不到。

    因为类型类很容易错过,但是look at Control.Arrow。普通的Arrows 不能被柯里化或应用,所以Arrow 组合符必然是无点的。如果你将它们专门用于(-&gt;),你会发现你想要的是这样的:

    (&&&) :: (Arrow a) => a b c -> a b c' -> a b (c, c')
    

    还有其他类似的函数,例如 Either 的等效操作,它专门用于 (-&gt;),如下所示:

    (|||) :: (a -> c) -> (b -> c) -> Either a b -> c
    

    either相同。

    出于好奇,我想以无点风格重写此函数,但我遇到了很多麻烦。

    由于您要复制输入,因此您需要某种方式来实现这一点——最常见的方式是通过(-&gt;)ApplicativeMonad 实例,例如\f g -&gt; (,) <$> f <*> g。这本质上是一个隐式的内联 Reader monad,被拆分的参数是“环境”值。使用这种方法,join f x 变为 f x xpurereturn 变为 constfmap 变为 (.),而 (&lt;*&gt;) 变为 (&lt;*&gt;) \f g x -&gt; f x (g x)

    【讨论】:

    【解决方案3】:

    实际上有很多方法可以做到这一点。最常用的方法是使用Control.Arrow中的(&amp;&amp;&amp;)函数:

    f &&& g
    

    但是,通常你有更多的函数或者需要将结果传递给另一个函数,在这种情况下使用 applicative 风格会更方便。那么

    uncurry (+) . (f &&& g)
    

    变成

    liftA2 (+) f g
    

    如上所述,这可以与多个功能一起使用:

    liftA3 zip3 f g h
    

    【讨论】:

    • 感谢,特别是“使用多个功能”的解释。
    • 这些当然可以用&lt;$&gt;&lt;*&gt;重写:zip3 &lt;$&gt; f &lt;*&gt; g &lt;*&gt; h。有时这比使用liftA* 更清楚。
    猜你喜欢
    • 2013-09-30
    • 1970-01-01
    • 2020-08-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-21
    • 2015-06-11
    相关资源
    最近更新 更多