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 to
case
)的模式匹配驱动的

在这种情况下,这并不重要,但您可以懒散地编写函数,以避免在不需要结果的情况下评估昂贵的计算,或者如果您知道始终需要某些结果,则严格地避免thunk的开销

一般来说,最好是将数据结构中的字段设置为严格的,除非您需要将其设置为懒惰的;将函数设置为懒惰的,除非您需要将其设置为严格的。在这里,您可以创建一个严格的对类型来表示向量:

data Vector a = Vector !a !a

嗯,这只是定义同一事物的不同风格。你的问题到底是什么?作为一般建议,我建议你尽可能多地学习使用模式匹配,至少在初学者阶段。使用
fst,snd
的替代方案是可以的,但在这里我看到太多初学者使用危险的函数,如
head,tail,fromJust
,这通常会导致崩溃,当模式匹配更加安全时,尤其是使用
-Wall
打开警告时(强烈建议)。这是真的,但可能太微妙了,对OP或任何从谷歌得到这个问题的人来说都没有用。谢谢你理解这个问题-我没有说得很好,因为我不认识Haskell!也许我应该跟着你的。