这是对我上一个问题的扩展:basic haskell : Copying elements
然而,当添加无效输入时,我希望它打印出一条错误消息,说“负值”或类似的东西。这在哈斯克尔有可能吗? 工作代码:
copy :: Int->a->[a]
copy 0 _ = []
copy y a = [a]++(copy (y-1) a)
最后一行:
copy b c = error "negative value"
答案 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"