Haskell 有像 Python 和 Ruby 这样的 splat 运算符吗?
Posted
技术标签:
【中文标题】Haskell 有像 Python 和 Ruby 这样的 splat 运算符吗?【英文标题】:Does Haskell have a splat operator like Python and Ruby? 【发布时间】:2011-10-26 15:05:42 【问题描述】:在 Python 和 Ruby 中(我敢肯定,还有其他)。您可以在枚举前面加上 *
("splat") 以将其用作参数列表。例如,在 Python 中:
>>> def foo(a,b): return a + b
>>> foo(1,2)
3
>>> tup = (1,2)
>>> foo(*tup)
3
Haskell 中有类似的东西吗?我认为由于它们的任意长度,它不适用于列表,但我觉得使用元组它应该可以工作。这是我想要的示例:
ghci> let f a b = a + b
ghci> :t f
f :: Num a => a -> a -> a
ghci> f 1 2
3
ghci> let tuple = (1,2)
我正在寻找一个允许我这样做的运算符(或函数):
ghci> f `op` tuple
3
我看到(<*>)
被称为“splat”,但它似乎与其他语言中的 splat 指的不是同一个东西。反正我试过了:
ghci> import Control.Applicative
ghci> f <*> tuple
<interactive>:1:7:
Couldn't match expected type `b0 -> b0'
with actual type `(Integer, Integer)'
In the second argument of `(<*>)', namely `tuple'
In the expression: f <*> tuple
In an equation for `it': it = f <*> tuple
【问题讨论】:
【参考方案1】:uncurry 函数将基于两个参数的函数转换为基于元组的函数。由于需要同质性,列表一般不会起作用。
【讨论】:
要明确一点:你是说它不能在任意长度的元组上完成,但 uncurry 适用于一对特殊情况? @gfxmonk:是的。元组中的每个数字组合和类型组合在 Haskell 的类型系统中都是不同的类型,因此函数不能接受每个元组类型。【参考方案2】:不,Haskell 的类型系统不喜欢这样。查看这个类似的问题了解更多详情:
How do I define Lisp’s apply in Haskell?
顺便说一句,您所说的 splat 运算符也称为 apply
函数,常见于动态函数语言(如 LISP 和 javascript)中。
【讨论】:
我相信这对于列表是正确的,但我专门询问了问题中的元组。 @gfxmonk:尽管如此,Python 中的枚举类似于列表,IMO,因为它们可以是任意长度并且 splat 的工作方式相同。在 Haskell 中,除非你使用深度魔法,否则你不能让函数处理任意元组。【参考方案3】:是的,您可以使用 tuple 包将函数应用于元组。尤其是uncurryN 函数,它可以处理多达 32 个元组:
Prelude Data.Tuple.Curry> (+) `uncurryN` (1, 2)
3
【讨论】:
我猜这使用了模板 Haskell? 谢谢,这是一种享受。不幸的是,它看起来只能被任意定义为最多 15 个元素的元组,但这可能已经很多了;) 是的,它必须为单个元组类型定义,因为在 Haskell 中,每个元组类型在技术上都是不同的类型。 (所以(a, b)
或“pair”是与(a, b, c)
或“triple”完全无关的类型——它们只是具有允许构造任意大的此类类型的特殊语法。)我不认为上面的包使用的是 Template Haskell,虽然我不认识“|”类定义中使用的符号。
@mgiuca:这里的“|”符号表示Functional Dependency。
@Chuck:元组包中没有模板 Haskell(尽管有一些自定义的 Haskell 代码将其他 Haskell 代码作为字符串发出)。以上是关于Haskell 有像 Python 和 Ruby 这样的 splat 运算符吗?的主要内容,如果未能解决你的问题,请参考以下文章
是否有像 Elgg 这样的插件可用于 Ruby on Rails?