【发布时间】:2014-04-03 02:25:29
【问题描述】:
我仍然掌握了 Haskell 的窍门,并且正在尝试构建我的第一个“真正的”编码项目,即我要包括测试、编写文档等的项目。我对 Haskell 足够陌生我知道我没有很多必要的语言知识,所以我想做的一切都触手可及,但这是一种想法,所以完成的动作需要我接触大部分语言的主要部分。
无论如何,我目前遇到的问题是关于在语言中抛出和捕获异常,我理解的事情可以通过多种方法来完成。我这里有个函数,toLower:
toLower :: String -> String
toLower plaintext =
if (catch (nonAlpha plaintext) handlerNonAlpha)
then map charToLower plaintext
else exitFailure
如果字符串包含任何非字母字符(所以如果不是 A-Z 或 a-z),或者如果不将字符串转换为小写,它将接受一个字符串,抛出异常并退出。所以我对 nonAlpha 函数的看法是:
--- detect non-alpha character - throw error if existant
data NonNumericException = NonNumException
instance Exception NonNumericException
handlerNonAlpha :: NonNumericException -> IO()
handlerNonAlpha ex =
putStrLn "Caught Exception: " ++ (show ex) ++ " - A non-alpha character was included in the plaintext."
nonAlpha :: String -> Bool
nonAlpha str =
let nonalphas = [x | x <- str, (ord x) < 65 || (90 < (ord x) && (ord x) < 97) || 123 < (ord x)]
in if (length nonalphas) == 0
then True
else throw NonNumException
正如我所说,我对 haskell 很陌生,所以我对这个数据/实例结构的工作原理有点模糊,但据我了解,我正在定义一个父级 NonNumericException,其中 NonNumException 是一个子级(我可以有更多),并在将它们定义为异常的实例行中。 catch 结构,如果它检测到异常(例如,如果有一个非字母字符,则在 nonAlpha 的末尾抛出一个异常),然后调用处理程序。
所以这是我得到的编译错误:
utilities.hs:61:3:
Couldn't match expected type `[Char]' with actual type `IO ()'
In the return type of a call of `putStrLn'
In the first argument of `(++)', namely
`putStrLn "Caught Exception: "'
In the expression:
putStrLn "Caught Exception: "
++
(show ex)
++ " - A non-alpha character was included in the plaintext."
utilities.hs:61:3:
Couldn't match expected type `IO ()' with actual type `[Char]'
In the expression:
putStrLn "Caught Exception: "
++
(show ex)
++ " - A non-alpha character was included in the plaintext."
In an equation for `handlerNonAlpha':
handlerNonAlpha ex
= putStrLn "Caught Exception: "
++
(show ex)
++ " - A non-alpha character was included in the plaintext."
utilities.hs:73:7:
Couldn't match expected type `Bool' with actual type `IO ()'
In the return type of a call of `catch'
In the expression: (catch (nonAlpha plaintext) handlerNonAlpha)
In the expression:
if (catch (nonAlpha plaintext) handlerNonAlpha) then
map charToLower plaintext
else
exitFailure
utilities.hs:73:14:
Couldn't match expected type `IO ()' with actual type `Bool'
In the return type of a call of `nonAlpha'
In the first argument of `catch', namely `(nonAlpha plaintext)'
In the expression: (catch (nonAlpha plaintext) handlerNonAlpha)
utilities.hs:75:8:
Couldn't match type `IO a0' with `[Char]'
Expected type: String
Actual type: IO a0
In the expression: exitFailure
In the expression:
if (catch (nonAlpha plaintext) handlerNonAlpha) then
map charToLower plaintext
else
exitFailure
In an equation for `toLower':
toLower plaintext
= if (catch (nonAlpha plaintext) handlerNonAlpha) then
map charToLower plaintext
else
exitFailure
所以我想我的两个问题是,a) 处理程序的类型出了什么问题(第 61 行错误),以及 b) 我如何正确设置可能引发异常或退出的函数的类型失败,否则会返回布尔值或字符串?
编辑:我想我应该注意。我确实看到了这个问题与其他一些被问到的问题之间的相似之处。我正在寻找但我没有看到的部分内容是对这里的结构实际在做什么的描述,最佳实践是什么以及为什么。
【问题讨论】:
-
我强烈建议使用
Either而不是例外。 -
感谢您的推荐,首先是为什么,其次,您能给我一个快速的流程指南吗?
-
第 61 行的错误只是优先级问题。
putStrLn $ "foo" ++ "bar"(或等效的putStrLn ("foo" ++ "bar"))将起作用。 -
@JackGibbs:原因是
Either是一流的,反映在类型系统中,而异常是不可见的。 bheklilr 的回答基本上是对我的建议的充实,但使用Maybe而不是Either。