当返回的对象不是字符串时,在Haskell中抛出异常。
所以我在Haskell中编写一个程序,它接收到一个数字n,告诉它返回从第2个素数开始的第n个素数,即第1个素数。该程序的那部分工作,但我不明白的是,如果数字为0或更少时,程序也会抛出异常。当返回的对象不是字符串时,在Haskell中抛出异常。
pr :: Int -> Int
pr n = (filter(\x -> (getter) == []) [2..]) !! (n-1)
该getter引用了另一个我写的解决主要问题的方法。它工作正常。
默认情况下,如果没有方程函数在给定参数匹配,你会得到一个运行时错误:
fromJust :: Maybe a -> a
fromJust (Just a) = a
-- No case for Nothing
-- fromJust Nothing throws error at runtime
然而,这不适用于数字工作。相反,守卫会做类似的事情:
assertOver0 :: Int ->()
assertOver0 n | n > 0 =()
-- No case for n <= 0
-- assertOver0 (-1) throws error at runtime
虽然这是默认的行为,这是不好的风格有不完整的图案/警卫。取而代之的是,明确地产生错误,error
或undefined
:
pr n | n >= 0 = filter (null . getter) [2..] !! n
| otherwise = error "Table flip"
-- undefined is just like error, except that error lets you give an error message
-- and undefined doesn't (undefined is more useful when you know it will never
-- be evaluated, and you don't need to give an error message)
-- undefined :: a; error :: String -> a
-- That is, they can take on any type you want them to have, because whatever code
-- is after them will never be executed anyway
-- I took liberties with your definition of pr. Your filtering function didn't use
-- x, so I wrote what I think you meant. I also made it 0-indexed.
-- Prelude.null checks for [], but doesn't incur an Eq constraint, so I replaced
-- (== []) with it.
-- Parens are not needed around the filter, because function application has
-- the highest precedence.
哈斯克尔也有Control.Exception
更复杂的异常处理机制,但你可能不需要在这里。一般而言,例外和部分功能被忽视(因为您只能在IO
中处理它们),您应该争取像Maybe
或Either
这样的单子。
import Control.Monad
pr n = do guard $ n >= 0 -- guard True = Just(); guard False = Nothing (in this case)
return $ filter (null . getter) [2..] !! n
pr 2 = Just 5
pr (-1) = Nothing
虽然这一切都是不必要的。 (!!)
已经在负指数
ghci> "abc" !! -1
*** Exception: Prelude.!!: negative index
错误,所以我们又回到了起点:
pr n = filter (null . getter) [2..] !! n
还有a library重新定义列表的操作(包括(!!)
)是一元,而不是局部的。
进一步的小改进:使用['null'](http://hackage.haskell.org/package/base-4.10.0.0/docs/Prelude.html#v:null)而不是'(== [])' 。更短,并且不会产生'Eq'约束:-) –
@ AntalSpector-Zabusky好抓! – HTNW
在Haskell中,基本上所有东西都只是一个库函数。因此,它可以很容易地发现与在线搜索引擎。这包括错误处理。因此,您可能需要ask Hayoo for error
或for raise
或for throw
。所有这三个存在 - 但raise
只在不同的口味,专门针对特定的图书馆,而throw
和error
是base
,因此“Haskell本身”的一部分。
-
throw
可以用来生产类型正确的例外,是合适的,如果你可以在某些时候,在你的程序本身,要抓 /分析错误。 -
error
只对崩溃的程序最有用,同时在终端上生成(希望)有用的诊断消息,这似乎是你想要的。
类型的error
是†,如GHC-8,
error :: HasCallStack => String -> a
的HasCallStack
是最近才加入,让程序告诉你其中在代码中出现错误。这不会改变您使用该功能的方式;在老版本的GHC的类型只是
error :: String -> a
也就是说,你只要给error
一些错误信息,然后用它作为任何功能,不管是什么结果类型功能的“结果”实际上应该是。在你的情况,
pr n | n >= 0 = ...
| otherwise = error "Table flip"
如果你给这个函数一个负数,则它将不会给任何实际的结果,但与消息Table flip
程序崩溃,并且在GHC> = 8,也告诉你,这个错误发生在pr
之内。
您可能还想知道,其中pr
被称为,以实际调试问题。您可以自己使用GHC调用堆栈模拟这样的:
import GHC.Stack
pr :: HasCallStack => Int -> Int
pr n | n >= 0 = ...
| otherwise = error "Table flip"
请注意,我并不需要改变以任何方式实现,我刚添加的HasCallStack
约束。
† 如果您在the documentation, as of GHC-8.2看,你将被示以一个相当可怕的签名
error :: forall (r :: RuntimeRep). forall (a :: TYPE r). HasCallStack => [Char] -> a
...不要担心,这些只是实施细节提升实际上,Haskell语言并没有如此自然地支持投掷。
文案 其他的答案给你一些很好的文字,所以我要在这里码重和轻解释。如果仍然不清楚的话请做评论,我会尽量填写它(或者你们任何常规的S.O.回答者都可以打败我)。
答案
你提出了一个问题,其中n <= 0
输入无效:
pr :: Int -> Int
pr n = (filter(\x -> (getter) == []) [2..]) !! (n-1)
最简单的解决方法是匹配模式或保护和手动抛出一个异常:
pr :: Int -> Int
pr n | n <= 0 = error "NO!"
| otherwise = ...
但有时你想要一个非字符串异常,在这种情况下你可能想要Control.Exception
:
{-# LANGUAGE DeriveAnyClass #-}
-- ^^^ This is not just a comment, enables a language extension
import Control.Exception as X
data MyException = ZeroOrNegative
deriving (Exception,Show,Eq,Ord)
-- ^^ N.B. you should derive 'Exception' for
-- types you want to 'throw'
pr n | n <= 0 = X.throw ZeroOrNegative
| otherwise = ...
找到您熟悉的函数的文档,然后单击Source按钮,然后查看它们的功能。一个例子就是'!!' – jberryman
我没有一个我很熟悉的,因为这是我第一次使用haskell – Darkhail
去体验(!!),点击[here](http://hoogle.haskell .ORG /?hoogle =(!!))。然后[这里](https://hackage.haskell.org/package/base-4.10.0.0/docs/Prelude.html#v:-33--33-)和[here](https:// hackage。 haskell.org/package/base-4.10.0.0/docs/src/GHC.List.html#%21%21)。和[这里](https://hackage.haskell.org/package/base-4.10.0.0/docs/src/GHC.List.html#negIndex)。要阅读更多关于您的主题,请尝试[this](http://learnyouahaskell.com/syntax-in-functions)并在那里搜索“警卫”。 –