我有以下功能:
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
和一个实际上没有正确类型的函数,但仍然有意义将折叠应用到?
答案 0 :(得分:6)
这里的问题与类型有关,即这会导致类型签名冲突。
我们举一个例子。如果我们接受这个:
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列表。所以使用一个列表。