【发布时间】:2016-02-23 10:54:36
【问题描述】:
我正在尝试将以下映射表示为 Haskell 函数:
给定两种类型 a, b 考虑函数族 F(a, b) 由类型的函数组成
f :: a -> a -> ... -> a -> b
n 重复 a,其中 n 是大于零的整数。
我想要的是将F(a, b) 中的每个函数f 映射到函数f' :: [a] -> b,这样f x1 x2 ... xr = f' [x1, ..., xr],其中r 小于f 需要的参数数量(即我正在寻找函数listify :: F(a, b) -> ([a] -> b))。如果元素多于 f 接受参数,则应丢弃额外的元素:
f :: a -> a -> b
(listify f xs) == (listify f $ take 2 xs)
此外,如果列出的为空,则任何值都可以接受。
我当然可以为具有固定数量参数的函数实现此映射(例如:listify :: (a -> a -> b) -> ([a] -> b) 等),但我找不到一种方法来编写一个对所有人都适用的函数f 同时在 F(a, b) 中。尽管 Template Haskell 可能能够为我提供正确的工具,但我对这样的解决方案不感兴趣。我想找到一些纯粹的“类型魔术”方式来做到这一点。
有人知道这是否可能吗?有人可以指出我正确的方向吗?或者这是一个已知的“问题”,已经解决了数十亿次,而我只是找不到解决方案?
【问题讨论】:
-
你可以用一些
OverlappingInstances技巧来做到这一点(也许即使是争议较少的扩展),但我怀疑这是一个好主意。为什么不直接使用 list-accepting 函数呢? -
关于“为什么?”:这是否可能的问题只是突然出现在我的脑海中 --> 我问的是教育原因(也许还学习了一些新的 Haskell 魔法,同时试图弄清楚出一个解决方案)。我对您指的是哪个“列表接受功能”感到有些困惑。我有一个函数 f :: a -> a -> ... a -> b(带有未知数量的 'a')并想要一个函数 f' :: [a] -> b,这样 f x1 .. . xr = f' [x1, ...., xr]。因此,我没有列表接受功能,我想要一个!但可能我没有明白你真正的意思。
-
您究竟会如何处理
OverlappingInstances以使其发挥作用?我看不出有什么办法。 -
嗯,是的,有可能,这基本上是像
printf这样的可变参数签名的双重问题。然而,这种多态性往往会导致问题。特别是,您的建议绕过了编译器的类型检查:通过推迟从运行时长度列表中获取固定数量的参数,编译器无法检查是否有足够的参数,因此您需要一个合理的错误案例...我可以看到这个有用的应用程序是解析,但最好使用 解析器组合器! -
有了“小论点”,你当然是对的。我只是想“嗯......只返回一个部分应用的函数。”。但是我刚才看到,这当然不会进行类型检查(甚至可能吗?我的意思是如果列表太短,则返回部分应用的函数)。关于有用性:我并不真正关心这种功能的应用程序/有用性/危险。我只是对如何去做感兴趣(我希望获得一些熟悉的 Haskell 知识 + 我认为
listify很有趣;))。
标签: haskell types higher-order-functions