【问题标题】:Is it possible to map tuple of functions over a list in Haskell?是否可以在 Haskell 中的列表上映射函数元组?
【发布时间】:2012-07-27 19:15:43
【问题描述】:

我正在努力寻找一种方法来做这样的事情:

(head, last) `someFunction` [1, 2, 3]

生成元组 (1, 3) 作为输出。

它在理论上似乎类似于应用函子,但有点倒退。我猜有一个类似的功能可以做到这一点(或某种方法),但我似乎无法找到它/弄明白。

我尝试定义这样的函数:

fmap' :: ((a -> b), (a -> b)) -> [a] -> (b, b)
fmap' (f1, f2) xs = (f1 xs, f2 xs)

但 GHC 不会真正编译它。

任何帮助都会很棒;谢谢!

编辑(一年后!):

我的fmap' 无法编译,因为类型签名错误。显然有更好的方法来做我正在做的事情,但我的 fmap' 的类型应该是:

fmap' :: ((a -> b), (a -> b)) -> a -> (b, b)

在这种情况下,它编译并运行得很好。

【问题讨论】:

  • 原来someFunctionuncurry (liftM2 (,)),根据pointfree。当然,您可以省略uncurry,而直接使用其余部分:liftM2 (,) head last [1, 2, 3]

标签: function haskell tuples applicative


【解决方案1】:

我认为你可以用箭头来做到这一点。

head &&& last $ [1,2,3]

将返回(1,3)

【讨论】:

  • 我对箭头还不熟悉,但我一直希望能更多地了解和使用它们。这很好而且可读。谢谢!
  • 有谁知道如何将其概括为两个以上的功能?例如,head &&& last &&& tail 会给您(1,(3,[2,3])),这并不理想。有没有一种简单的方法可以将其展平为一个元组?
  • @JeffreyBurka 我也经历过这个。我认为tuple-flattening 函数会违反Haskell 的严格类型系统,因为n-tuplesn-tuples,仅此而已。该函数的类型签名没有意义(您必须输出动态大小的tuple,这是不可能的。)
  • 是的,元组肯定没有concat,但我在想可能有一种简单的方法可以将箭头表示为返回三元组而不是嵌套元组的箭头。如果这不可能或不容易,那么我会使用 Daniel Wagner 的应用解决方案。
  • 实际上我认为使用arrow do notation 可能很简单。我现在没有 GHC,不幸的是,Codepad 使用 Hugs,所以我目前无法测试。
【解决方案2】:

它在理论上似乎类似于应用函子,但有点倒退。

实际上,这是一个无聊的老前锋应用函子;具体来说,读者((->) r)

Prelude Control.Applicative> liftA2 (,) head last [1,2,3]
(1,3)

或者,如果你喜欢这样的事情:

Prelude Control.Applicative> let sequenceA [] = pure []; sequenceA (x:xs) = (:) <$> x <*> sequenceA xs
Prelude Control.Applicative> [head, last] `sequenceA` [1,2,3]
[1,3]

【讨论】:

    【解决方案3】:

    fmap' 的类型错误。应该是

    fmap' :: ([a] -> b, [a] -> b) -> [a] -> (b, b)
    

    或者,它可以更通用

    fmap' :: (a -> b, a -> c) -> a -> (b, c)
    

    它并不像fmap :: (a -&gt; b) -&gt; f a -&gt; f b

    【讨论】:

    • 啊!我实际上尝试了一些不起作用的方法,但我才意识到我正在调用fmap 而不是fmap'。我想知道为什么它不能正常工作。感谢您的快速回复!
    【解决方案4】:

    在这种情况下可以尝试省略类型签名并检查 GHC 推断的内容。

    这样做并询问 GHCi :t fmap' 会产生签名

    fmap' :: (t2 -> t, t2 -> t1) -> t2 -> (t, t1)
    

    这与 KennyTM 的通用版本相同,并会为您提供您正在寻找的行为。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-10-12
      • 2016-07-31
      • 1970-01-01
      • 1970-01-01
      • 2012-09-27
      • 2019-09-08
      • 1970-01-01
      • 2012-09-08
      相关资源
      最近更新 更多