我正在查看这个问题,了解如何获取多个列表并将它们转换为列表列表。我有以下几点:
Prelude> x1 = [1,2,3]
Prelude> x2 = [4,5,6]
Prelude> x3 = [7,8,9]
Run Code Online (Sandbox Code Playgroud)
我想看到一些 \function 这可能是可变参数:
Prelude> xs = map (\function -> ???) x1 x2 x3
Prelude> show xs -- that produces this
[[1,2,3], [4,5,6], [7,8,9]]
Run Code Online (Sandbox Code Playgroud)
或者没有映射,其他一些可变参数函数 F 使得:
Prelude> xs = F x1 x2 x3 ... x1000
Prelude> show xs -- that produces this
[[1,2,3], [4,5,6], [7,8,9], ...., [1000000,1000001,1000002]]
Run Code Online (Sandbox Code Playgroud)
我对答案的期望是类似
Prelude> map (:) x1 x2 x3 []
<interactive>:26:1: error:
• Couldn't match expected type ‘[Integer]
-> [Integer] -> [a0] -> t’
with actual type ‘[[Integer] -> [Integer]]’
• The function ‘map’ is applied to five arguments,
but its type ‘(Integer -> [Integer] -> [Integer])
-> [Integer] -> [[Integer] -> [Integer]]’
has only two
In the expression: map (:) x1 x2 x3 []
In an equation for ‘it’: it = map (:) x1 x2 x3 []
• Relevant bindings include it :: t (bound at <interactive>:26:1)
Run Code Online (Sandbox Code Playgroud)
或者
Prelude> map (:) $ x1 x2 x3 []
<interactive>:27:11: error:
• Couldn't match expected type ‘[Integer]
-> [Integer] -> [a0] -> [a]’
with actual type ‘[Integer]’
• The function ‘x1’ is applied to three arguments,
but its type ‘[Integer]’ has none
In the second argument of ‘($)’, namely ‘x1 x2 x3 []’
In the expression: map (:) $ x1 x2 x3 []
• Relevant bindings include
it :: [[a] -> [a]] (bound at <interactive>:27:1)
Run Code Online (Sandbox Code Playgroud)
我也没有在 Hoogle 中找到这种函数,但可能错误地指定了类型签名:
https://www.haskell.org/hoogle/?hoogle=%5Ba%5D+-%3E+%5Ba%5D+-%3E+%5B%5Ba%5D%2C%5Ba%5D%5D
Haskell 中的多变量函数很难实现。这是因为一个函数基本上只能有一个参数,因此只有通过柯里化才能包含更多参数,这将参数的数量烘焙到函数的类型中。
然而,这并不意味着这是不可能的,尽管有时这需要使用扩展。在这里,我将按照复杂性递增的顺序进行一些介绍。这可能不会很有用,但可能会有所帮助。
有点切题的是,几年前我制作了一个多变量函数示例的存储库,您可能会发现这些示例很有趣,但它们完全相同且质量可疑;即使现在我也不是专业人士,那是几年前的事了。
一个简单但粗略的方法就是定义多个函数来制作一个包含n 个元素的列表,例如:
makeList1 :: a -> [a]
makeList2 :: a -> a -> [a]
-- etc.
-- Use:
myList = makeList5 1 2 3 4 5
Run Code Online (Sandbox Code Playgroud)
这不是那么美妙。我们能做得更好吗?
FlexibleInstances)这更有趣。在这里,我们牺牲了特异性来创建一个真正的多变量函数:
{-# LANGUAGE FlexibleInstances #-}
class MkIntList r where
mkIntList' :: [Int] -> r
-- No arguments
instance MkIntList [Int] where
mkIntList' = id
-- One argument, then some others
instance (MkIntList r) => MkIntList (Int -> r) where
mkIntList' xs x = mkIntList' (xs ++ [x]) -- (Inefficient, but this is an illustration)
-- The variadic function
mkIntList :: (MkIntList r) => r
mkIntList = mkIntList []
-- Use:
myList1 = mkIntList 1 2 3 :: [Int] -- myList1 = [1,2,3]
myList2 = mkIntList :: [Int] -- myList2 = []
Run Code Online (Sandbox Code Playgroud)
我会让你去了解这个。
FlexibleInstances和FunctionalDependencies)这是前一个的多态版本,其中我们必须通过函数依赖来跟踪类型。
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FunctionalDependencies #-}
class MkList a r | r -> a where
mkList' :: [a] -> r
instance MkList a [a] where
mkList' = id
instance (MkList a r) => MkList a (a -> r) where
mkList' xs x = mkList' (xs ++ [x]) -- (Again inefficient)
mkList :: (MkList a r) => r
mkList = retList []
-- Use:
myList1 = mkList 'H' 'i' '!' :: String -- myList1 = "Hi!"
myList2 = mkList True False :: [Bool] -- myList2 = [True, False]
Run Code Online (Sandbox Code Playgroud)
我认为这在理论上是最不有趣的解决方案,所以我不会进入坦率乏味的例子。
此方法涉及创建一个函数,该函数通过模板 Haskell 依次生成 Haskell 代码,然后可以使用它在编译时根据此列表的长度生成必要的函数。这本质上是方法 1 的劳动密集度较低(但在编译时较慢)的版本。
现在可能有更多的方法可以做到这一点,但我希望这些例子对您有所帮助,或者至少具有启发性。