我编写了一个 haskell 函数,它将列表 xs
拆分为 (init xs, last xs)
,如下所示:
split xs = split' [] xs
where
split' acc (x:[]) = (reverse acc, x)
split' acc (x:xs) = split' (x:acc) xs
由于空列表不能以这种方式拆分,因此与空列表不匹配。但是,我不想简单地让函数出错...
。因此,我定义了以下内容:
split [] = ([], undefined)
由于惰性求值,我可以定义一个安全的 init
,它只是返回空列表的空列表:
init' = fst . split
如果我尝试访问,是否有某种方法可以检测到未定义的内容它,这样
last' xs
| isUndefined (snd xs) = ...
| otherwise = ...
我就知道也许
和要么
,并且这些是表达我想要的更好的选择。但是我想知道是否有一种方法可以检测未定义的实际值,即捕获错误,例如捕获异常。
I've written a haskell function which splits a list xs
into (init xs, last xs)
like so:
split xs = split' [] xs
where
split' acc (x:[]) = (reverse acc, x)
split' acc (x:xs) = split' (x:acc) xs
Since an empty list can not be split in this way, there is no match for the empty list. However, I did not want to simply error ...
the function. Thus I defined the following:
split [] = ([], undefined)
Thanks to lazy evaluation I can thus define a safe init
which simply returns the empty list for the empty list:
init' = fst . split
Is there some way how I could detect the undefined if I tried to access it, such that
last' xs
| isUndefined (snd xs) = ...
| otherwise = ...
I do know about Maybe
and Either
, and that those are a better choice for expressing what I want. However I wondered if there is a way to detect an actual value of undefined, i.e. in terms of catching errors, like catching exceptions.
发布评论
评论(5)
undefined
并不比使用error
更好。事实上,Prelude 中的undefined
是 定义为现在,不会导致
错误
的函数被称为“总函数”,即它对所有输入值都有效。您当前实现的 split 函数具有签名
这是一个问题,因为类型签名承诺结果始终包含一个列表和一个元素,这显然不可能提供泛型的空列表类型。
Haskell 中解决此问题的规范方法是更改类型签名,以表明有时我们没有第二项的有效值。
现在您可以为获得空列表的情况编写正确的实现
现在您可以通过模式匹配来检测缺失值的情况
undefined
is no better than usingerror
. In fact,undefined
in Prelude is defined asNow, a function that can't result in an
error
is called a "total function", i.e. it is valid for all input values.The
split
function you've currently implemented has the signatureThis is a problem, since the type signature promises that the result always contains a list and an element, which is clearly impossible to provide for empty lists of generic type.
The canonical way in Haskell to address this is to change the type signature to signify that sometimes we don't have a valid value for the second item.
Now you can write a proper implementation for the case where you get an empty list
Now you can detect the missing value case by pattern-matching
因为bottom包含非终止,所以函数
isUndefine
必须解决暂停问题,因此不能存在。但请注意,即使它存在,您仍然无法判断元组第二个元素中的未定义值是否通过 split 函数放入其中,或者列表的最后一个元素是否已未定义。
Because bottom subsumes non-termination, the function
isUndefined
would have to solve the halting problem and thus cannot exist.But note that even if it existed, you still could not tell if the undefined value in the 2nd element of your tuple was put there through your
split
function or if the last element of the list was already undefined.error
函数在评估之前不会执行任何操作,因此您可以执行以下操作:The
error
function doesn't do anything until it is evaluated, so you can do something like:来自 Haskell 2010 语言报告 >简介 # 值和类型
需要明确的是,
undefined
旨在成为一种将 ⊥ 插入到程序中的方法,并且考虑到(如 shang 所指出的)undefined
是根据error 定义的
,因此,“没有检测或作用于未定义
的机制”。From the Haskell 2010 Language Report > Introduction # Values and Types
To be clear,
undefined
is intended to be a way to insert ⊥ into your program, and given that (as shang noted)undefined
is defined in terms oferror
, there is, therefore, "no mechanism for detecting or acting uponundefined
".虽然从语义上讲,Ingo 的答案是正确的,但如果您使用 GHC,有一种方法可以使用几个“不安全”函数,尽管不太完美,就像您传递给它一个包含异常的 IO a 类型的计算一样,它会返回True,有效。不过,这有点作弊:)。
我知道这很可怕,但它仍然有效。但它不会检测到非终止;)
Although semantically speaking Ingo's answer is correct, if you're using GHC, there is a way using a couple of "unsafe" functions that, although not quite perfect as if you pass it a computation of type IO a which contains an exception it will return True, works. It's a bit of a cheat though :).
I know this is horrible, but none the less it works. It won't detect non termination though ;)