繁体   English   中英

Haskell模式匹配向量

[英]Haskell Pattern Match Vectors

我正在关注Haskell的在线教程 我们定义了一个函数来添加二维向量,由元组对数字表示。 以下是显式类型声明,它确保两个输入都是二维向量。

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总是返回一个元组,其元素可能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到case )。

在这种情况下并不重要,但是如果你的结果永远不需要,你可以懒散地编写你的函数以避免评估昂贵的计算,或者如果你知道总是需要一些结果,那么严格来避免thunk的开销。

一般来说,最好使数据结构的字段严格,除非你需要它们是懒惰的,并且除非你需要它们是严格的,否则你的函数会变得懒惰。 在这里你可以制作一个严格的对类型来表示你的向量:

data Vector a = Vector !a !a

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM