我有以下功能:
brace_it :: a -> b -> (a, b)
brace_it a b = (a, b)
我可以用它正确地获得brace_it (brace_it (brace_it 1 2) 3) 4
(((1,2),3),4)
。
但我想做foldl brace_it 0 [1,2,3,4]
。然而这是不可能的,因为brace_it
没有正确的签名(它需要b -> a -> b
)。然而,从概念上讲,用它折叠列表是有意义的,我认为,获得与将其手动应用于1
,...,4
相同的结果。是否有可能建立插入foldl
/ foldr
之间的东西和一个实际上没有正确类型但仍然有意义地应用折叠的函数?
这里的问题与类型有关,即这会导致类型签名冲突。
我们来举个例子吧。如果我们这样做:
foldl brace_it 0 [1] = (0,1) --(Not correct Haskell)
所以,显然,foldl brace_it 0 :: [Int] -> (Int, Int)
。然而:
foldl brace_it 0 [1,2] = ((0,1),2) --(Not correct Haskell)
所以,显然,foldl brace_it 0 :: [Int] -> ((Int, Int), Int)
。这是假的。
那么,为什么这在理论上不可能呢?因为Haskell程序要求你在编译时知道所有类型 - 你不能创建一个可以构造(Int, Int)
或((Int, Int), Int)
的函数 - 你需要做一些类型的杂技。例如,您可以构造一个类型,允许您将任意多个事物组合在一起:
data Pairs a = None | Pair a (Pairs a)
然后你的brace_it
功能将成为brace_it a b = Pair a (Pair b None)
。
但是,这完全等同于普通的Haskell列表。所以使用一个列表。