gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-02 13:31:51 25 4
gpt4 key购买 nike

我想知道如何返回一个非常简单的字符串异常。我编写了一个“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"

最佳答案

Haskell 的异常系统故意功能不足。您无法在纯代码中捕获异常,因此异常处理只能发生在 IO monad 内部的非常粗粒度的级别。完全阻止异常导致程序崩溃是相当困难的(尽管有可能)。 (想象一下,如果您只能在命令式程序的 main 方法中编写 catch!)因此,我们尽可能避免抛出异常;有一个更好的选择。

在 Haskell 中进行异常式编程的“正确方法”是利用类型系统。这里我使用Either来表示计算失败的可能性。

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

如果我们无法计算答案,我们将返回一个包含 StringLeft 值 (Left::a -> Either a b) > 错误消息。否则,我们返回包含答案的 Right (Right::b -> Either a b)。

编译器强制 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

Natural 是一种包装 Int 的类型。作为 Data.Natural 模块的客户端,只有一种方法可以创建 Natural:通过调用 mkNatural“智能构造函数”,并且您会看到当参数不是自然数时,mkNatural 会失败。因此,如果没有正整数,就不可能生成自然数。我们还提供了相反的方法,toInt::Natural -> Int,从 Natural 中提取底层 Int

现在我们可以为 powered 编写以下类型签名,这使得使用无效输入调用函数不可能:

powered :: Natural -> Natural

这更具表现力:类型签名清楚地表明powered是对自然数的运算,它返回一个新的自然数。 (我将把它作为练习,让您使用此类型实现powered。)通过将输入验证的关注点分离到新类型中,我们最终得到了具有更清晰的代码。

关于haskell - 如何在 Haskell 中返回字符串异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26579258/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com