Haskell中如何更新构造器值?含函数实现与空构造器疑问
Haskell 构造器更新问题
我想根据给定值更新Submission构造器的字段,定义的构造器如下:
data Submission = Submission { session :: String, quizName :: String, student :: String } deriving (Eq,Show)
我要写一个update函数,类型签名是:
update :: (String, String) -> Maybe Submission -> Maybe Submission
这个函数的逻辑是:接收一个字符串元组(第一个元素是字段名,第二个是目标值),当目标Submission的对应字段为空字符串时,就更新该字段;如果字段已有值,就返回原Submission。
我现在写的代码存在问题,代码如下:
update (String, String)-> Maybe Submission -> Maybe Submission update x y | fst x == "session" && Submission {session = Nothing } = return Submission {session = snd x} | fst x = "quizName" && Submission {quizName = Nothing} = return Submission {quizName = snd x} | fst x = "student" && Submission {student = Nothing} = return Submission {student = snd x} | otherwise = y
另外还有个疑问:空的Submission是不是应该写成这样?
Submission {student = "",quizName = "",student =""}
现有代码的问题
- 类型签名语法错误:正确的类型签名格式是
update :: (String, String) -> Maybe Submission -> Maybe Submission,你把类型String直接放在参数位置的写法不符合Haskell语法。 - 字段值判断错误:
session等字段的类型是String,不是Maybe String,不能用Nothing判断空值,应该判断是否为空字符串""。 - 未处理
Maybe容器:函数第二个参数是Maybe Submission,需要先对Just s或Nothing做模式匹配,不能直接用变量y进行条件判断。 - 字段更新不完整:
Submission {session = snd x}这种写法会丢失其他字段的原有值,应该用记录更新语法保留其他字段。
正确实现代码
update :: (String, String) -> Maybe Submission -> Maybe Submission update (field, val) Nothing = Nothing -- 传入Nothing时直接返回空 update (field, val) (Just s) = Just $ case field of "session" -> if session s == "" then s { session = val } else s "quizName" -> if quizName s == "" then s { quizName = val } else s "student" -> if student s == "" then s { student = val } else s _ -> s -- 字段名不匹配时返回原对象
空构造器的正确写法
你给出的写法存在重复定义student字段的错误,正确的空值构造器需要给每个字段都赋值为空字符串:
Submission {session = "", quizName = "", student = ""}
如果Submission没有定义默认字段值,必须显式给所有字段赋值,否则会编译报错。
内容的提问来源于stack exchange,提问作者Mon
相关产品推荐
相关产品推荐

