Haskell:使用静态元素和列表从元组创建元组列表

时间:2015-09-30 06:12:40

标签: haskell

需要使用静态元素和列表从元组创建元组列表。如:

(Int, [String]) -> [(Int, String)]

感觉这应该是一个简单的map调用,但实际上遇到输出元组时遇到麻烦,因为zip需要列表输入,而不是常量。

4 个答案:

答案 0 :(得分:4)

我认为这是最直接易懂的解决方案(无论如何你似乎已经熟悉了map):

f :: (Int, [String]) -> [(Int, String)]
f (i, xs) = map (\x -> (i, x)) xs

(这也恰好是Landei提出的[(i, x) | x < xs]的desugared版本)

然后

Prelude> f (3, ["a", "b", "c"])
[(3,"a"),(3,"b"),(3,"c")]

此解决方案使用模式匹配来“解包”元组参数,以便第一个元组元素为i,第二个元素为xs。然后,它会对map的元素执行简单的xs,将每个元素x转换为元组(i, x),我认为这就是您所追求的。没有模式匹配,它会更加冗长:

f pair = let i  = fst pair  -- get the FIRST element
             xs = snd pair  -- get the SECOND element
         in map (\x -> (i, x)) xs

<强>此外:

该算法并非特定于(Int, [String]),因此您可以使用类型参数IntString替换ab来安全地概括该功能:

f :: (a, [b]) -> [(a, b)]
f (i, xs) = map (\x -> (i, x)) xs

这样你可以做到

Prelude> f (True, [1.2, 2.3, 3.4])
[(True,1.2),(True,2.3),(True,3.4)]

当然,如果你只是简单地删除类型注释,那么类型(a, [b]) -> [(a, b)]正是Haskell推断的类型(只有不同​​的名称):

Prelude> let f (i, xs) = map (\x -> (i, x)) xs
Prelude> :t f
f :: (t, [t1]) -> [(t, t1)]

加分:您还可以使用\x -> (i, x)语言扩展程序将(i,)简化为TupleSections

{-# LANGUAGE TupleSections #-}

f :: (a, [b]) -> [(a, b)]
f (i, xs) = map (i,) xs

另外,正如ØrjanJohansen指出的那样,函数sequence确实进一步概括了这一点,但其机制有点超出了范围。

答案 1 :(得分:2)

为完整起见,请同时考虑cycle

f i = zip (cycle [i])

使用foldl

f i = foldl (\a v -> (i,v) : a ) []

使用递归函数说明如何划分问题,

f :: Int -> [a] -> [(Int,a)]
f _ [] = []
f i (x:xs) = (i,x) : f i xs

答案 2 :(得分:2)

列表理解将非常直观和可读:

f (i,xs) = [(i,x) | x <- xs]

答案 3 :(得分:0)

您希望Int始终相同,只需将zip与无限列表一起提供。您可以使用repeat

f i xs = zip (repeat i) xs