Haskell模式匹配向量
我正在关注一个在线的问题。我们定义了一个函数来添加二维向量,用元组对数字表示。下面是显式类型声明,它确保两个输入都是二维向量Haskell模式匹配向量,haskell,vector,pattern-matching,Haskell,Vector,Pattern Matching,我正在关注一个在线的问题。我们定义了一个函数来添加二维向量,用元组对数字表示。下面是显式类型声明,它确保两个输入都是二维向量 addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a) 我理解为什么下面的函数定义使用模式匹配:它描述了输入数据应该符合的模式 addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2) 为什么下面的替代函数定义不使用模式匹配?(fst)和(snd)保证工作,
addVectors :: (Num a) => (a, a) -> (a, a) -> (a, a)
我理解为什么下面的函数定义使用模式匹配:它描述了输入数据应该符合的模式
addVectors (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
为什么下面的替代函数定义不使用模式匹配?(fst)和(snd)保证工作,因为输入被显式声明为长度为2的元组
这两个函数定义之间有什么区别
addVectors a b = (fst a + fst b, snd a + snd b)
它们在严格程度上有所不同。假设我们重命名它们:
> let addVectorsStrict (x1, y1) (x2, y2) = (x1 + x2, y1 + y2)
> let addVectorsLazy a b = (fst a + fst b, snd a + snd b)
addVectorsStrict undefined undefined
为undefined
-只要需要结果的外部(,)
构造函数,就会执行模式匹配:
> case addVectorsStrict (error "A") (error "B") of (_, _) -> ()
*** Exception: A
但是addVectorsLazy undefined undefined
是(undefined,undefined)
-模式匹配被延迟,直到需要结果的一个元素
> case addVectorsLazy (error "A") (error "B") of (_, _) -> ()
()
基本上,addVectorsLazy
总是返回一个元组,其中的元素可能未赋值addVectorsStrict
可能不会返回。您还可以使用惰性模式匹配获得addVectorsLazy
的效果:
> let addVectorsAlsoLazy ~(x1, y1) ~(x2, y2) = (x1 + x2, y1 + y2)
> case addVectorsAlsoLazy (error "A") (error "B") of (_, _) -> ()
()
为了更好地理解求值顺序,可以使用Debug.Trace.Trace
观察求值顺序:
addVectors
(trace "first tuple evaluated"
(trace "x1 evaluated" 1, trace "y1 evaluated" 2))
(trace "second tuple evaluated"
(trace "x2 evaluated" 3, trace "y2 evaluated" 4))
关于Haskell中的求值,需要记住的一点是,它是由使用case
和函数方程(desugar tocase
)的模式匹配驱动的
在这种情况下,这并不重要,但您可以懒散地编写函数,以避免在不需要结果的情况下评估昂贵的计算,或者如果您知道始终需要某些结果,则严格地避免thunk的开销
一般来说,最好是将数据结构中的字段设置为严格的,除非您需要将其设置为懒惰的;将函数设置为懒惰的,除非您需要将其设置为严格的。在这里,您可以创建一个严格的对类型来表示向量:
data Vector a = Vector !a !a
嗯,这只是定义同一事物的不同风格。你的问题到底是什么?作为一般建议,我建议你尽可能多地学习使用模式匹配,至少在初学者阶段。使用
fst,snd
的替代方案是可以的,但在这里我看到太多初学者使用危险的函数,如head,tail,fromJust
,这通常会导致崩溃,当模式匹配更加安全时,尤其是使用-Wall
打开警告时(强烈建议)。这是真的,但可能太微妙了,对OP或任何从谷歌得到这个问题的人来说都没有用。谢谢你理解这个问题-我没有说得很好,因为我不认识Haskell!也许我应该跟着你的。