在Haskell中通过部分应用减少列表

在Haskell中通过部分应用减少列表,haskell,Haskell,对于具有多个参数的函数,是否有更强大的map版本?因此,缩减列表的长度将是原始长度/参数数量 tuple a b = (a, b) map' tuple [1, 2, 3, 4] > [(1, 2), (3, 4)] mul a b c = a * b * c map' mul [1, 2, 3, 4, 5, 6] > [3, 120] 我试着给自己写一个,但似乎不可能接受任何数量的参数的作用 我想为可变数量的参数提供通用版本,因为每次自己编写一个参数需要一些时间,而且不会使用循

对于具有多个参数的函数,是否有更强大的map版本?因此,缩减列表的长度将是原始长度/参数数量

tuple a b = (a, b)
map' tuple [1, 2, 3, 4]
> [(1, 2), (3, 4)]

mul a b c = a * b * c
map' mul [1, 2, 3, 4, 5, 6]
> [3, 120]
我试着给自己写一个,但似乎不可能接受任何数量的参数的作用


我想为可变数量的参数提供通用版本,因为每次自己编写一个参数需要一些时间,而且不会使用循环融合。

最简单的解决方案是只生成一个helper函数 对于您需要的每种类型,例如,对于类型3函数:

map3 :: (a -> a -> a -> b) -> [a] -> [b]
map3 f (x : y : z : rest) = f x y z : map3 f rest
map3 f _ = []
将它们放在实用程序模块中,以便根据需要导入它们。 如果你想变得复杂,你可以使用 TemplateHaskell、CPP宏,甚至类型类,但要小心 把这个简单的练习变成一个牦牛剃须派对

你的例子是:

interact $ unlines . fmap foo . tuple . lines
然后可以表示为:

interact $ unlines . map2 foo . lines

假设
foo
有签名
foo::String->String->String

,我不同意这样定义的精神,但只是出于它的哈索奇主义,我正在尝试。这是一个有效的解决方案,但仅适用于单态类型。我正在研究是否可以将其转换为一些涉及类型族的内容,而不需要添加类型注释

{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, FlexibleContexts #-}

class Consumer f a b where
  consume :: f -> [a] -> Maybe (b,[a])

instance {-# OVERLAPPABLE #-} Consumer b a b where
  consume b xs = Just (b,xs)

instance {-# OVERLAPPING #-} Consumer f a b => Consumer (a -> f) a b where
  consume f [] = Nothing
  consume f (x:xs) = consume (f x) xs

map' :: Consumer f a b => f -> [a] -> [b] 
map' f xs = case consume f xs of
                Nothing -> []
                Just (b,xs') -> b : map' f xs'
并进行测试

> map' ((+) :: Int -> Int -> Int) ([1,2,3,4] :: [Int]) :: [Int]
[3,7]
> map' (id :: Int -> Int) ([1,2,3,4] :: [Int]) :: [Int]
[1,2,3,4]
编辑
经过一番思考,我认为不可能有更好的解决方案(没有依赖类型)。我必须到处添加类型注释的原因是,我无法通知GHC我提供的两个使用者实例实际上是我想要的唯一实例(是封闭类型类吗?),而且我无法消除函数依赖关系。第二个问题也是为什么我不能将其重写为类型族。不过,另一方面,现在我们有了
TypeApplications
map”((+)@Int)([1..9]:[Int])

Ye,我现在正在做,但是map3不会受到融合的影响。或者会吗?那将是一个很好的,独立的问题。也许有人会用一种方法来回答是否发生了融合。如果没有,那么就没有必要编写自己的列表操作函数。@FordO。这是一个有点宽泛的说法。。。还有,你所说的融合到底是什么意思?您希望看到哪些转换/重写?你可以用列表函数编写Erik的函数,这些函数需要融合。例如,
map3f=snd。foldr(\a(as,bs)->{[a2,a1]>([],f a1 a2 a:bs);->(a:as,bs)}([],[])
…@BenjaminHodgson有趣的是,“流融合”论文在结尾(9.2融合通用递归定义)提到了尝试“融合列表上的通用递归定义”的可能性。但我认为这样的事情从来没有实现过,不可能以一种好的方式实现。在第二个示例中,map如何知道您不想要一个三元素函数列表的结果?也就是说,如果所有类型都已知,一些重载魔法可以做到这一点。@augustss我正在尝试这一点(见下面的答案),我在解决多态类型的问题时遇到了一些问题。您是否愿意在回答的“如果所有类型都已知”部分进行扩展?