【问题标题】:Composing a chain of 2-argument functions组成一个 2 参数函数链
【发布时间】:2011-12-08 17:45:24
【问题描述】:

所以我有一个[a -> a -> a] 类型的两个参数的函数列表

我想编写一个函数,它将获取列表并将它们组合成一个函数链,该函数链采用左侧组成的长度 + 1 个参数。例如,如果我有 [f,g,h] 所有类型的 [a -> a -> a] 我需要编写一个函数,它给出:

chain [f,g,h] = \a b c d -> f ( g ( h a b ) c ) d

此外,如果有帮助,这些函数的参数是可交换的(即,f x y = f y x 代表所有 x y)。

鉴于我知道相关函数的数量,我可以在列表理解中执行此操作,它几乎与定义完全相同。从固定数量的函数到动态数量的延伸让我很困惑。

这是我目前所拥有的:

f xs = f' xs
    where
        f' []   = id
        f' (x:xs) = \z -> x (f' xs) z

我认为逻辑是正确的,只是没有进行类型检查。

提前致谢!

【问题讨论】:

  • 它不进行类型检查,因为它不可能进行类型检查。尝试用带有列表的函数替换带有未知数量参数的函数。这就是列表的用途,用来保存未知数量的类似类型的东西。

标签: haskell function-composition


【解决方案1】:

n.m. 的评论是正确的——这不能以任何传统方式完成,因为结果的类型取决于输入列表的长度。你需要一个更高级的类型系统来完成这项工作。你可以在 Haskell 中妥协,使用一个在类型中编码其长度的列表,但这很痛苦和尴尬。

相反,由于您的参数都是相同的类型,因此创建一个接受值列表而不是多个参数的函数会更好。所以你想要的类型是这样的:chain :: [a -> a -> a] -> [a] -> a

有几种方法可以编写这样的函数。从概念上讲,您希望从参数列表的前面和函数列表的末尾开始,然后将第一个函数应用于第一个参数以获得a -> a 类型的内容。从那里,将该函数应用于下一个参数,然后将下一个函数应用于结果,从每个列表中删除一个元素,并为您提供一个 a -> a 类型的新函数。

您还需要处理列表长度不正确匹配的情况。除了前面提到的类型编码长度和与之相关的麻烦之外,没有其他办法。

【讨论】:

    【解决方案2】:

    我想知道,您的“具有功能列表”要求是真正的要求还是解决方法?我遇到了同样的问题,但在我的情况下,函数集很小并且在编译时已知。更准确地说,我的任务是用 xor 压缩 4 个列表。我想要的只是一个紧凑的符号来组成 3 个二进制函数。我用的是一个小帮手:

    -- Binary Function Chain
    bfc :: (c -> d) -> (a -> b -> c) -> a -> b -> d
    bfc f g = \a b -> f (g a b)
    

    例如:

    ghci> ((+) `bfc` (*)) 5 3 2 -- (5 * 3) + 2
    17
    ghci> ((+) `bfc` (*) `bfc` (-)) 5 3 2 1 -- ((5 - 3) * 2) + 1
    5
    ghci> zipWith3 ((+) `bfc` (+)) [1,2] [3,4] [5,6]
    [9,12]
    ghci> getZipList $ (xor `bfc` xor `bfc` xor) <$> ZipList [1,2] <*> ZipList [3,4] <*> ZipList [5,6] <*> ZipList [7,8]
    [0,8]
    

    这并没有按原样回答原始问题,但希望仍然可以提供帮助,因为它几乎涵盖了问题主题行的内容。

    【讨论】:

    • 比较\f g a b -&gt; f (g a b)((.) . (.)) 的类型。 :)
    • 威尔尼斯,啊,好样的!我知道一定有这么简单的事情,但我自己却没有发现……谢谢!
    猜你喜欢
    • 2019-05-10
    • 2017-10-27
    • 2013-03-27
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-10-26
    相关资源
    最近更新 更多