据我了解,Haskell的undefined
值 - 特定类型 - 是一个无法确定的值,无论出于何种原因(可能没有合理的定义,或者计算方法不同).例如:undefined :: [Int]
是一个列表,所以它必须用[]或(:)构造,但它不知道哪一个!因此,有意义的是,未定义的案例拆分使得整个表达式未定义:我不知道null (undefined :: [a])
是真还是假,因为我不知道是否undefined :: [a]
为空.
(顺便说一句-如果你用我的建议,不同意undefined
在建有一个构造函数,那么肯定null (undefined :: [a])
应该评估为False毕竟?undefined
不等同于[]!)
但是,Haskell模式匹配并不遵循这种思维方式.
data Foo = Foo Int String -- Only one data constructor silly :: Foo -> Bool silly (Foo _ _) = True ghci> silly (undefined :: Foo) *** Exception: Prelude.undefined -- But whatever the value is, it must -- be constructed with Foo. -- So why fail to match?
(我知道newtype在这里表现不同.)
也:
foo :: Int -> String -> Bool foo 8 "Hello" = True foo _ _ = False ghci> foo undefined undefined *** Exception: Prelude.undefined -- GOOD - can't tell which case to choose. ghci> foo undefined "Hello" *** Exception: Prelude.undefined -- GOOD - still can't tell. ghci> foo undefined "Goodbye" *** Exception: Prelude.undefined -- BAD - should return false! -- Pattern match on first line should fail, -- because whatever the int is, the -- string can't match the given pattern.
我认为关于模式匹配的规则目前说如果子模式失败那么模式应该立即失败; 如果它发散,那么整个模式也应该分歧; 如果成功,则应尝试下一个子模式.如果所有子模式都成功,则整个模式成功.
我的建议是,如果任何子模式失败,那么整个模式应该失败; 如果没有失败,但有些分歧,那么整个模式应该分歧; 如果一切顺利,那么整个模式应该成功.
为什么这不是Haskell的工作方式?
编辑:
总结一下我对我读过的回答的解释:
undefined
应该被理解为"这将导致你的程序永远运行"而不是"这个定义不明确",Exception: Prelude.undefined
应该被理解为"注意!如果未定义是一个无限循环你的程序将永远不会终止"而不是"我不要不知道该怎么办,因为我不知道undefined是什么价值".
有人可以验证这是正确的吗?如果是这样,那么我可能会接受mb14的回答.
感谢大家.对不起因为速度太慢了!
基本上,你是说undefined :: Foo
和Foo undefined undefined
,因为(你说的应该是相同的But whatever the value is, it must be constructed with Foo.)
.
这种假设是不正确的.富必须与构造Foo
,只有当它能够建造.如果我有foo = if x then (Foo 1 "a") else (Foo 2 "b")
.如果x
未定义则尝试评估f
分歧.那时,没有构造函数的概念.它只是分歧.
这是你的榜样一样null (undefined :: [a])
应该是undefined
(发散),以及因为你需要尝试评估的参数null
就知道如果它是一个[]
或一个:
.
在Haskell中未定义并不神奇,它只是一个循环.你可以定义自己的loop = let x = x in x
.每次尝试评估它时都会循环.调用null loop
或sill loop
将循环因此等于loop
,不是吗?你还在考虑那个loop :: Foo
并且Foo loop loop
是一样的吗?我不.我希望silly loop
循环但不是silly (Foo loop loop)
.
这之间的唯一区别loop
,并undefined
仅仅是GHC可以检测undefined
是一个循环,并因此打破了外观和显示错误消息,而不是无休止的循环下去的.它只是为了方便,如果不存在,人们会定义undefined = loop
.
(顺便说一句 - 如果你不同意我的建议,undefined是用构造函数构建的,那么肯定null(undefined :: [a])应该计算为False吗?毕竟undefined不等于[]!)
这意味着它不应该评估True
,也不应该评估.
我的建议是,如果任何子模式失败,那么整个模式应该失败; 如果没有失败,但有些分歧,那么整个模式应该分歧; 如果一切顺利,那么整个模式应该成功.
怎么能实现呢?要查找第一个子模式是否失败,您需要评估该参数; 如果它发散,评估将无法完成,整个模式匹配也会因定义而异.您可以尝试"并行"评估所有模式,但这会使语言复杂化:当前定义将多个方程式转换case
为第一个参数,然后是第二个参数,等等,因此它不会介绍任何新概念; 你的必须.
我不会说" undefined
应该代表一个非终止计算",但你不应该能够区分它们:
Haskell中的错误在语义上等同于⊥("bottom").从技术上讲,它们与不确定无法区分,因此该语言不包括检测错误或对错误采取行动的机制.但是,实现可能会尝试提供有关错误的有用信息.见3.1节.