【问题标题】:Haskell - My own zip3 functionHaskell - 我自己的 zip3 函数
【发布时间】:2018-06-14 14:03:51
【问题描述】:

有没有更好的方法来重新创建这个函数?它编译得很好。

这就是我所拥有的:

zip3' :: [a] -> [b] -> [c] -> [(a,b,c)]
zip3' [] _ _ = []
zip3' _ [] _ = []
zip3' _ _ [] = []
zip3' (a:as) (b:bs) (c:cs) = (a,b,c) : zip3' as bs cs

我只是想知道是否有更好的方法来总结这一点:

zip3' [] _ _ = []
zip3' _ [] _ = []
zip3' _ _ [] = []

【问题讨论】:

    标签: list haskell zip tuples


    【解决方案1】:

    它工作正常。如果想让程序更短,可以这样写:

    zip3' :: [a] -> [b] -> [c] -> [(a,b,c)]
    zip3' (a:as) (b:bs) (c:cs) = (a,b,c) : zip3' as bs cs
    zip3' _      _      _ = []
    

    因为只有在三个列表中至少有一个不是(_:_)(所以[])时,第一行才会触发。但这有时被视为一种反模式,因为在一个非常不同的事件中,将构造函数添加到列表数据类型,这可能会以一个空列表结束(而在这种情况下,我们可能最好得到一个错误)。我同意对于列表来说这几乎是不可能的:很多库和程序将不再工作。但通常情况下,您例如设计一个数据类型,然后改变主意并添加一个额外的构造函数。

    如果我们检查zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]的源代码,那么我们看到它是这样实现的[source]

    zip3 :: [a] -> [b] -> [c] -> [(a,b,c)]
    -- Specification
    -- zip3 =  zipWith3 (,,)
    zip3 (a:as) (b:bs) (c:cs) = (a,b,c) : zip3 as bs cs
    zip3 _      _      _      = []
    

    出于某种原因,zip 本身以“问题”风格实现 [source]

    zip :: [a] -> [b] -> [(a,b)]
    zip []     _bs    = []
    zip _as    []     = []
    zip (a:as) (b:bs) = (a,b) : zip as bs
    

    【讨论】:

    • 比我说完全相同的话,但你更详细。打得很好。
    • 看起来docs 指定zip 是右懒,但zip3 没有这样的限制。这将解释实现中的差异,它还提出了一个有趣的观点,即以我以前没有考虑过的 OP 风格编写代码的好处。
    • @SilvioMayolo:据我所知,模式匹配是从左到右完成的。所以它也会首先将第一个参数与(a:as)匹配,所以afaik,语义上没有区别。无论如何,我们都提到了前奏曲的源代码,这很有趣:)
    • 嗯...我似乎无法构建一个反例。看来您对语义的理解是正确的。
    【解决方案2】:

    您的方法本质上没有任何问题,但您可以在最后将前三个案例合并为一个包罗万象的案例。

    zip3' :: [a] -> [b] -> [c] -> [(a,b,c)]
    zip3' (a:as) (b:bs) (c:cs) = (a,b,c) : zip3' as bs cs
    zip3' _ _ _ = []
    

    其实这是how GHC does it

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-17
      • 2016-11-29
      • 1970-01-01
      • 2016-01-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多