Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/css/38.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/webpack/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何在Haskell中返回字符串异常?_Haskell - Fatal编程技术网

如何在Haskell中返回字符串异常?

如何在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”,它接受整数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          =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