如何在Haskell中返回字符串异常?
我想知道如何返回一个非常简单的字符串异常。我编写了一个函数“powered”,它接受整数n,并返回2^(n)。代码如下:如何在Haskell中返回字符串异常?,haskell,Haskell,我想知道如何返回一个非常简单的字符串异常。我编写了一个函数“powered”,它接受整数n,并返回2^(n)。代码如下: powered::Int->Int powered n | n==1 =2 | otherwise =iter n double 1 国际热核实验堆: iter::Int->(Int->Int)->Int->Int iter n f x | n==1 =f x | n>1 =
powered::Int->Int
powered n
| n==1 =2
| otherwise =iter n double 1
国际热核实验堆:
iter::Int->(Int->Int)->Int->Int
iter n f x
| n==1 =f x
| n>1 =iter (n-1) f (f x)
| otherwise =x
双倍:
double::Int->Int
double n = n*2
此代码适用于所有自然数。一、 但是,如果我向它传递一个负整数,它将返回一个字符串异常,该异常表示:“输入不正确”。我怎样才能做到这一点。下面是我想要实现的伪代码:
powered::Int->Int
powered n
| n==0 =1
| n==1 =2
| n>1 =iter n double 1
| otherwise ="Incorrect input"
main = do
print(powered (-1)) ~> "Incorrect input"
最简单的方法是通过
错误:
error "Incorrect input"
GHC实现引发了一个errorCallException
异常:
error :: [Char] -> a
error s = raise# (errorCallException s)
使用相应的字符串
另一种选择是使用断言:
assert (n >= 0) (iter n double 1)
这将不允许您指定错误消息,但它将自动提供失败的断言的文件和行号
最后,您可以使用如下自定义异常(使用Control.exception
):
然后:
throw (PoweredError "Incorrect input")
只需使用error
抛出IOError:
| otherwise = error "Incorrect input"
这是在Haskell中抛出错误的标准方法。虽然非典型,但可以通过首先将类型声明为Exception类的实例来抛出任意类型(如string)的错误:
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE FlexibleInstances #-}
import Control.Exception
instance Exception [Char] -- String can now be used as an Exception
main :: IO ()
main = catch (print foo)
(\(e :: String) -> putStrLn $ "Caught: " ++ e)
-- foo is a computation that might throw an error
foo :: String
foo = throw "foo"
Haskell的异常系统故意断电。您无法在纯代码中捕获异常,因此异常处理只能在IO
monad中的非常粗粒度级别上进行。要阻止一个异常完全破坏您的程序是相当困难的,尽管这是可能的。(想象一下,如果您只能在命令式程序的main
方法中编写catch
),那么我们将尽可能避免抛出异常;还有一个更好的选择
在Haskell中进行异常风格编程的“正确方法”是利用类型系统。这里我用它来表示计算失败的可能性
powered :: Int -> Either String Int
powered n
| n <= 0 = Left "Incorrect input"
| n==1 = Right 2 -- Right means "the right answer"
| otherwise = Right $ iter n double 1
Natural
是一种包装Int
的类型。作为Data.Natural
模块的客户机,只有一种方法可以生成Natural
:调用mkNatural
“智能构造函数”,您将看到mkNatural
的参数不是自然数时失败。因此,如果没有一个正整数,就不可能使一个自然的。我们还提供了相反的方法,toInt::Natural->Int
,从Natural
中提取底层Int
现在我们可以为powered
编写以下类型签名,这使得无法使用无效输入调用函数:
powered :: Natural -> Natural
这是一种更具表现力的方式:类型签名清楚地表明,powered
是对自然数的操作,它返回一个新的自然数。(我将把它留作一个练习,让您使用这种类型实现powered
)。通过将输入验证的关注点分离到一个新类型中,我们得到了更干净的代码
-- file Natural.hs
-- don't export the 'Natural' value constructor: 'mkNatural' acts as our "gatekeeper"
module Data.Natural (Natural, toInt, mkNatural) where
newtype Natural = Natural {toInt :: Int} deriving (Eq, Show)
mkNatural :: Int -> Either String Natural
mkNatural x
| x <= 0 = Left "Must be greater than 0"
| otherwise = Right $ Natural x
powered :: Natural -> Natural