所以foldr const 0 "tacos"
应该解散成类似
0 const ('t' const ('a' const ('c' const ('o' const 's')))).
我认为它只会在0 const ('t'
处停止,因为Haskell是惰性计算的,而const只接受第一个参数。因此,从理论上讲,该函数是否不适用于1?
虽然这不起作用。用0
替换""
也不起作用。有人知道为什么吗?
谢谢!
为什么文件夹const 0“ tacos”在Haskell中不能编译?
因为:
> foldr const 0 "tacos"
<interactive>:1:13: error:
• No instance for (Num Char) arising from the literal ‘0’
• In the second argument of ‘foldr’, namely ‘0’
In the expression: foldr const 0 "tacos"
In an equation for ‘it’: it = foldr const 0 "tacos"
因此,如果我们进行调查,我们会看到(请忽略@[]
,它是一种类型应用程序,可以使我们的对话更加简单)
> :t foldr @[] const 0
foldr @[] const 0 :: Num b => [b] -> b
因此您需要提供Num
实例的项目列表。但您提供了:
> :t "tacos"
"tacos" :: [Char]
玉米饼有时是包裹肉和米饭的玉米饼。但是有时,例如现在,它们是字符列表。字符不是Num
的实例。这就是错误要告诉您的内容。
查看文件夹的类型(让我们专门研究列表):
foldr :: (a -> b -> b) -> b -> [a] -> b
您已经提供了参数(并且我们将Int专门指定为0)
const :: a -> b -> b -- this looks off...
0 :: b -- this means b = Int
"tacos" :: [a] -- this means a = Char
稍等。检查const的实际类型:
const :: a -> b -> a
看到问题了吗?您以错误的顺序获得了const
的参数。尝试使用(flip const)
而不是const
获得所需的答案,尽管它没有所需的性能特征。
您可能还想尝试foldl'
,它从左到右累积结果。
以您最初编写它的方式,类型系统必须将const的类型签名a -> b -> a
与文件夹的参数类型a -> b -> b
统一,这只能通过统一a = b
来完成。但是,由于a = Char
和b = Int
,无法执行此统一。
[表达式的正确“解散”(foldr
的工作方式是将:
替换为const
,将[]
替换为0
。
't' : 'a' : 'c' : 'o' : 's' : []
==> let's write it with (:) as a prefix funtion
(:) 't' ((:) 'a' ((:) 'c' ((:) 'o' ((:) 's' []))))
==>
const 't' (const 'a' (const 'c' (const 'o' (const 's' 0))))
但由于上述所有const
都必须具有相同的类型的限制,因此不能。
注意0
如何显示在innermost常量而不是最外部。
我猜你犯了两个错误:一个很小,另一个稍微小一些。
要将带字母的变量(例如const
)用作运算符,必须将其括在反引号中:
"hello" `const` 1 = "hello"
"hello" const 1 -- nonsense
您将foldr
与foldl
部分混在一起:
foldr (#) n [1..3] = 1 # (2 # (3 # n))
foldl (#) b [1..3] = ((b # 1) # 2) # 3
确实,foldl
与const
正常工作:
foldl const 0 "tacos"
= ((((0 `const` t) `const` a) `const` c) `const` o) `const` s
= 0
这种愚蠢的计算效率很低,即使结果始终相同,也需要遍历整个列表才能将const 0
应用于每个元素!