haskell:如何为我的函数报告错误

时间:2013-10-18 19:25:02

标签: haskell

这是对我上一个问题的扩展:basic haskell : Copying elements

然而,当添加无效输入时,我希望它打印出一条错误消息,说“负值”或类似的东西。这在哈斯克尔有可能吗? 工作代码:

copy :: Int->a->[a]
copy 0 _ = [] 
copy y a = [a]++(copy (y-1) a)

最后一行:

copy b c  = error "negative value"

3 个答案:

答案 0 :(得分:6)

因为部分功能让我很难过,所以我建议你做更多的事情

copy :: Int -> a -> Maybe [a]
copy 0 _ = Just []
copy n a | n < 0 = Nothing
         | otherwise = fmap (a:) (copy (n-1) a)

我们已将if替换为“后卫”

foo bar | baz = quux
        | ...

只是

 foo bar = if baz then quux else ...

请注意,我也稍微更改了您的代码,

 [a] ++ copy (y-1) a ====> fmap (a:)  (copy (y-1) a)

您可以将(:)视为追加。

 1 : [2, 3] ==> [1, 2, 3]

它是[1] ++ [2, 3]的首选替代品。大声说出“cons”,就像“构造”一样。我们可以用运算符部分来写这个

(a:) ==> \x -> a : x

接下来我们使用这个不稳定的fmap函数。想想fmap就像这样

fmap f Nothing = Nothing
fmap f (Just x) = Just (f x)

因此它会解包Just并在重新包装结果之前应用一个函数。因此,如果我们的数字为负数,我们的最终代码将返回Nothing,否则只返回列表。

为什么我不推荐error?好吧,因为error会以非常小的信息炸毁整个程序,尝试捕获它是个坏主意。 Haskell甚至没有强制要求这样做,GHC只是以可能的方式实现error。换句话说,你几乎没有机会恢复。

对于10行代码来说这不是什么大问题,但是我花了6个多小时使用error搜索对函数的违规调用。它的调试速度要快得多,而且还有更多惯用的哈希尔。

答案 1 :(得分:1)

你可以用警卫

来做到这一点
copy :: Int -> a -> [a]
copy n x
    | n < 0 = error "negative value"
    | n == 0 = []
    | otherwise = x : copy (n - 1) x

但是,如果失败,则可能会导致程序崩溃。更好的方法是使用Maybe类型:

copySafe :: Int -> a -> Maybe [a]
copySafe n x 
    | n < 0 = Nothing
    | otherwise = Just (copy n x)

然后你可以用它作为

main = do
    putStrLn "Enter a number:"
    nStr <- getLine
    let n = read nStr :: Int
        maybeXs = copySafe n n
    case maybeXs of
        Nothing -> putStrLn "You entered a negative number!"
        Just xs -> print xs

此样式强制您考虑copySafe的两种情况,或者它可以在负值上失败,或者它可以返回有效列表。它不会使程序崩溃,并且类型系统会强制执行错误处理。

答案 2 :(得分:-6)

查看http://www.haskell.org/haskellwiki/Error_vs._Exception

例如

copy b c = if c > b then error "negativ value"