- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我想知道如何返回一个非常简单的字符串异常。我编写了一个“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
如果我们无法计算答案,我们将返回一个包含 String
的 Left
值 (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/
我是一名优秀的程序员,十分优秀!