我有以下Haskell表达式:
3 : [40] ++ [50] ++ 5 : [60]
我想知道这个表达式是如何计算的。哪个运算符具有更高的优先级:
或++
?
我认为表达式的结果是[3,40,50,5,60],但是我是通过以下方式做到的:
3 : [40] ++ [50] ++ 5 : [60]
3 : [40] ++ [50] ++ [5,60]
3 : [40] ++ [50,5,60]
3: [40,50,5,60]
[3,40,50,5,60]
以上是计算表达式的正确方法吗?任何见解都表示赞赏。
答案 0 :(得分:8)
我们可以将(++) :: [a] -> [a] -> [a]
和 (:) :: a -> [a] -> [a]
函数都以 5
作为优先级读Haskell '10 report,并且是正确的关联。
我们还可以在:i
shell中用ghci
获取此数据:
Prelude> :i (:)
data [] a = ... | a : [a] -- Defined in ‘GHC.Types’
infixr 5 :
Prelude> :i (++)
(++) :: [a] -> [a] -> [a] -- Defined in ‘GHC.Base’
infixr 5 ++
因此,这意味着:
3 : [40] ++ [50] ++ 5 : [60]
的缩写:
3 : ([40] ++ ([50] ++ (5 : [60])))
(++)
运算符是implemented as:
(++) :: [a] -> [a] -> [a] (++) [] ys = ys (++) (x:xs) ys = x : xs ++ ys
(:)
是一个数据构造函数,因此,它不能被“进一步评估”。
这是有道理的,因为这意味着++
仅在此处应用于尾巴,因此,只要我们对头部感兴趣,就不需要评估该函数。因此,右联想(++)
通常比左联想(++)
便宜,尽管它会产生相同的列表。
因此,如果我们要评估完整列表,则将其评估为:
3 : ([40] ++ ([50] ++ (5 : [60])))
-> 3 : (40 : ([] ++ ([50] ++ (5 : [60]))))
-> 3 : (40 : ([50] ++ (5 : [60])))
-> 3 : (40 : (50 : ([] ++ (5 : [60]))))
-> 3 : (40 : (50 : (5 : [60])))
或更详细:
3 : ((40: []) ++ ((50 : []) ++ (5 : (60 : []))))
-> 3 : (40 : ([] ++ ((50 : []) ++ (5 : (60 : [])))))
-> 3 : (40 : ((50 : []) ++ (5 : (60 : []))))
-> 3 : (40 : (50 : ([] ++ (5 : (60 : [])))))
-> 3 : (40 : (50 : (5 : (60 : []))))