哪一个成熟的图书馆"脆弱"列出Haskell的操作?

时间:2014-03-16 07:19:31

标签: list haskell

在经过几年乱丢乱的图书馆之后,我开始提出这个问题并提出这样的定义:

fragileZip :: [t1] -> [t2] -> [(t1, t2)]
fragileZip a b = loop a b
  where
    loop [] []           = []
    loop (h1:t1) (h2:t2) = (h1,h2) : loop t1 t2
    loop _ _             = error "fragileZip: lists were not the same length."

我的经验是,在Haskell前奏中做出的决定 - 关于takedropzip等不会因为元素不足而错误 - 允许使用无限列表的可爱技巧,并且在某些情况下可能很方便,但是,例如,当预计长度相同的压缩列表时,它们是静默失败的狡猾来源。

是否有人知道一个完整的Data.List替换,试图成为"脆弱的"像上面的zip一样,如果不满足期望,总是会抛出错误:如果列表长度不匹配,或者元素不足?

[脚注:是的,用总功能编程是好的,但这意味着用类型级信息释放相关证明义务,而不是通过返回错误值来掩盖错误!标准zip悄然丢失数据可能就是这样一种无声的失败。另外,我并不关心如何传达错误结果(例外,可能或者是其中之一)。如果现有的hackage lib适合账单,我会采取任何措施!]

3 个答案:

答案 0 :(得分:4)

safe包中包含来自Prelude的许多函数的“更安全”版本;它们不会抛出错误,而是在失败时返回Maybe值。但是,您仍将在运行时检测错误。

errors包重新导出safe中的函数,并添加其他便利函数以进行错误处理。

如果您愿意深入研究Haskell的新的依赖类型功能,sized-vector包提供了在编译时检查其大小的列表。特别是,zipSame函数只能压缩具有相同长度的列表:

{-# LANGUAGE DataKinds #-}

import Data.Vector.Sized
import Data.Type.Natural

vec2 :: Vector Char Two
vec2 = 'a' :- 'b' :- Nil

vec3 :: Vector Char Three
vec3 = 'x' :- 'y' :- 'z' :- Nil

vecZipped = zipSame vec2 vec3

此代码在编译时失败,错误为:

Couldn't match type 'S Zero with 'Z
Expected type: Vector Char Two
  Actual type: Vector Char Three
In the second argument of `zipSame', namely `vec3'
In the expression: zipSame vec2 vec3
In an equation for `vecZipped': vecZipped = zipSame vec2 vec3

有关sized-vector和Haskell上的依赖类型的教程,请参阅herecomments也有有用的信息。

(有时候,你想要的是不同大小的压缩列表。我经常将有限列表压缩为无限列表,因为后者更容易定义。)

答案 1 :(得分:3)

我认为你提出的问题违背了Haskell的哲学。涉及error或任何其他运行时崩溃的代码由于正当理由而不好。

但很明显,如果你愿意,可以自己创建一个包装器:

fragileZip :: [a] -> [b] -> [(a,b)]
fragileZip x y = if length x == length y
                 then zip x y
                 else error "Not of the same length"

如果您确实想在结果类型中展示一些错误,请使用类型MaybeEither。例如:

fragileZip :: [a] -> [b] -> Maybe [(a,b)]
fragileZip x y = if length x == length y
                 then Just $ zip x y
                 else Nothing

答案 2 :(得分:1)

您的zip可以在list-extras包中找到pair。还有safe个包,虽然它会解决headtail及其错误的错误,而不是zipdrop等。