我尝试编写一个练习程序。如果它可以根据给定的语法解析String,则它应该读取一个String并返回一个空列表。如果字符串的语法无效,则应返回“ Nothing”。像这儿:
>prog "c+c*c$"
Just""
>prog "c+c-c$"
Nothing
我编写了以下函数,它们在GHCI中加载和编译,但是当我prog
使用任何参数运行时,都会收到以下异常:*** Exception: Maybe.fromJust: Nothing
我想我以错误的方式访问或传递Maybe字符串,但不确定在哪里。欢迎提供有关正确处理Maybe结构的帮助。
这是我的代码:
import Data.Maybe
match :: Char -> Maybe String -> Maybe String
match x input
| (isNothing input == False) && (x == head (fromJust(input))) = Just (tail (fromJust(input)))
| otherwise = Nothing
prog :: String -> Maybe String
prog x = match '$' (expr (Just (x)))
expr :: Maybe String -> Maybe String
expr x = ttail (term x)
term :: Maybe String -> Maybe String
term x = ftail (factor x)
ttail :: Maybe String -> Maybe String
ttail x
| fromJust(x) == [] = Just []
| otherwise = ttail (term (match '+' x))
factor :: Maybe String -> Maybe String
factor x = match 'c' x
ftail :: Maybe String -> Maybe String
ftail x
| fromJust(x) == [] = Just []
| otherwise = ftail ( factor ( match '*' x))
OP的代码中有几种反模式。我只讨论这个片段。
match :: Char -> Maybe String -> Maybe String
match x input
| (isNothing input == False) && (x == head (fromJust(input))) = Just (tail (fromJust(input)))
| otherwise = Nothing
isNothing, fromJust
是一种反模式,因为后者是一个部分函数,当使用时会导致程序崩溃Nothing
。程序员必须小心,要始终isJust
事先检查,这很容易忘记。完全忘记这些功能,而改为依靠模式匹配要容易得多(请参见下文)。.. == False
应该改写为 not ..
not (isNothing ..)
应该是isJust ..
(但同样,模式匹配使这一点毫无意义)head,tail,!!
也是部分函数,应在可能的情况下将其替换为模式匹配。上面head
可能会调用[]
,因此我们需要事先进行检查。模式匹配避免了需要。.. == []
可以使用null ..
(或者更好的是模式匹配)代替。f(x)
为函数调用而写,括号在此处无用。-Wall
标志打开警告:编译器经常发现代码中的问题。如果您正在学习Haskell,我强烈建议您不要使用危险的部分函数,而是阅读有关模式修补的教程,使用它可以防止代码中的几乎所有问题。
为了进行比较,可以将以上代码重写为:
match :: Char -> Maybe String -> Maybe String
match x (Just (y:ys)) | x==y = Just ys
match _ _ = Nothing
请注意,模式匹配如何同时检查参数是否为a Just
,且内部具有非空列表,并提取构造函数内部的数据。如果失败,则采用下一种匹配情况(而不是使程序崩溃)。
在没有模式匹配的语言中(例如Java),通常库会迫使我们记住x.hasNext()
访问数据之前检查数据是否存在x.next()
。忘记检查会导致运行时错误/异常。使用模式匹配时,这两个步骤以相同的语言结构组合在一起,因此无法“忘记”检查并使程序崩溃。
与原始代码不同,match x (Just [])
不会崩溃,而是返回Nothing
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句