使用列表的内容作为单个多参数函数的位置参数 [英] Use contents of a list as positional arguments to a single multi-argument function
问题描述
是否有标准的 Haskell 函数(或模式)来提取列表的内容并将它们作为函数的有序位置参数提供给它们?
Is there a standard Haskell function (or pattern) to extract the contents of a list and feed them as though they are the ordered positional arguments to a function?
例如,考虑函数 (,)
,当给定两个位置参数时,将从它们生成一个二元组:
For example, consider the function (,)
which, when given two positional arguments, will make a two-tuple from them:
(,) 3 4 --> (3,4)
假设我有一些无法更改的外部函数调用给我的参数,表示为列表 [3, 4]
.
Suppose instead I have these arguments given to me by some external function call that I cannot change, represented as a list [3, 4]
.
是否有内容"操作,这样才能工作:
Is there a "contents of" operation, such that this would work:
(,) $ contents_of [3, 4]
这样 contents_of
的动作就好像这些项目被放置在源代码中一样,它们之间有空格作为函数应用程序?
so that the action of contents_of
behaves just as though the items had been placed in source code with spaces between them as function application?
例如,(,) $contents_of [1]
应该是柯里化函数 ((,) 1)
然后再接受一个参数来完成元组的创建.
For example, (,) $ contents_of [1]
should be the curried function ((,) 1)
which then takes one more argument to complete creating the tuple.
我的一个想法是尝试将函数折叠到列表上,折叠函数表示柯里化:
One thought I had was to try to fold the function over the list, with the fold function expressing currying:
foldr (\x y -> y x) (,) [3, 4]
但是查看foldr
的类型签名:
foldr :: (a -> b -> b) -> b -> [a] -> b
让这看起来很困难.b
这里需要是函数类型本身,但是当它被应用于参数时,它不会是一个与 b
不再,导致折叠中的类型问题.
makes this seem difficult. b
here would need to be the function type itself, but then by the time it has been applied to the arguments it won't be a function with the same type signature as b
any longer, leading to type issues in the fold.
这在本质上类似于 Python *args
构造.
This is similar in spirit to the Python *args
construct.
我不关心这可能暗示的严格属性——只是在标准 Haskell 中是否可以实现这样的事情.
I'm not concerned with the strictness properties this might imply -- just whether something like this is possible in standard Haskell.
推荐答案
可以像这样表示 N 元函数:
It is possible to represent N-ary functions like so:
data FunN r a = FunN Int (a -> FunN r a) | FNil r
然后将普通函数转换成FunN
:
Then convert plain functions into FunN
:
f2FunN :: (FunN (a->b) a) -> FunN b a
f2FunN (FNil g) = FunN 1 (FNil . g)
f2FunN (FunN n g) = FunN (n+1) (f2FunN . g)
然后应用参数列表:
a :: FunN b a -> [a] -> b
a (FNil r) [] = r
a (FunN _ f) (x:t) = a (f x) t
a _ _ = error "wrong arity"
例如:
Prelude> a (f2FunN $ f2FunN $ FNil (+)) [1,2]
3
Prelude> a (f2FunN $ FNil (+)) [1] 2
3
Prelude> a (f2FunN $ f2FunN $ FNil (+)) [1,2,3]
*** Exception: wrong arity
Prelude> a (f2FunN $ f2FunN $ FNil (+)) [1]
*** Exception: wrong arity
但当然你需要在编译时知道函数的arity——这样你才能知道你可以用f2FunN
包装函数多少次.
But of course you need to know the arity of the function at compile time - so that you know how many times you can wrap the function with f2FunN
.
这篇关于使用列表的内容作为单个多参数函数的位置参数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!