组合 2 参数函数链

发布于 2024-12-20 09:29:27 字数 619 浏览 0 评论 0原文

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

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

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

此外,如果有帮助的话,这些函数在它们的参数中是可交换的(即对于所有x yfxy = fy x) )。

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

这就是我到目前为止所得到的:

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

我认为逻辑是沿着正确的路径,它只是不进行类型检查。

提前致谢!

So I have a list of a functions of two arguments of the type [a -> a -> a]

I want to write a function which will take the list and compose them into a chain of functions which takes length+1 arguments composed on the left. For example if I have [f,g,h] all of types [a -> a -> a] I need to write a function which gives:

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

Also if it helps, the functions are commutative in their arguments ( i.e. f x y = f y x for all x y ).

I can do this inside of a list comprehension given that I know the the number of functions in question, it would be almost exactly like the definition. It's the stretch from a fixed number of functions to a dynamic number that has me stumped.

This is what I have so far:

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

I think the logic is along the right path, it just doesn't type-check.

Thanks in advance!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

音盲 2024-12-27 09:29:27

nm 的评论是正确的——这不能以任何常规方式完成,因为结果的类型取决于输入列表的长度。您需要一个更高级的类型系统才能实现这一点。在 Haskell 中,你可以通过使用一个在类型中编码其长度的列表来妥协,但这是痛苦和尴尬的。

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

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

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

The comment from n.m. is correct--this can't be done in any conventional way, because the result's type depends on the length of the input list. You need a much fancier type system to make that work. You could compromise in Haskell by using a list that encodes its length in the type, but that's painful and awkward.

Instead, since your arguments are all of the same type, you'd be much better served by creating a function that takes a list of values instead of multiple arguments. So the type you want is something like this: chain :: [a -> a -> a] -> [a] -> a

There are several ways to write such a function. Conceptually you want to start from the front of the argument list and the end of the function list, then apply the first function to the first argument to get something of type a -> a. From there, apply that function to the next argument, then apply the next function to the result, removing one element from each list and giving you a new function of type a -> a.

You'll need to handle the case where the list lengths don't match up correctly, as well. There's no way around that, other than the aforementioned type-encoded-lengths and the hassle associate with such.

不打扰别人 2024-12-27 09:29:27

我想知道,您的“拥有功能列表”要求是真正的要求还是解决方法?我面临着同样的问题,但就我而言,函数集很小并且在编译时已知。更准确地说,我的任务是用异或压缩 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) <
gt; ZipList [1,2] <*> ZipList [3,4] <*> ZipList [5,6] <*> ZipList [7,8]
[0,8]

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

I wonder, whether your "have a list of a functions" requirement is a real requirement or a workaround? I was faced with the same problem, but in my case set of functions was small and known at compile time. To be more precise, my task was to zip 4 lists with xor. And all I wanted is a compact notation to compose 3 binary functions. What I used is a small helper:

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

For example:

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) <
gt; ZipList [1,2] <*> ZipList [3,4] <*> ZipList [5,6] <*> ZipList [7,8]
[0,8]

That doesn't answers the original question as it is, but hope still can be helpful since it covers pretty much what question subject line is about.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文