haskell - 为什么 GHC 不能确定在这个案例语句中使用哪个字段?
问题描述
{-# LANGUAGE DuplicateRecordFields #-}
resolveProjectConfig :: IO (Maybe ProjectConfig)
config :: IO ()
config = do
config <- resolveProjectConfig
case config of
Just c -> putStrLn (name c)
Nothing -> putStrLn "broken"
GHC 似乎知道Just c
c 是 a ProjectConfig
,但是在putStrLn (name c)
我得到错误“不明确的出现名称。它可以引用字段名称... [具有名称字段的其他内容列表]”。
当然,如果它知道是什么c
,它应该能够选择正确的名称功能吗?有没有办法让它弄清楚,而不添加c :: ProjectConfig
?
解决方案
这是 GHC 的当前限制。我们需要写name (c :: ProjectConfig)
来消除歧义。不是很方便。
作为替代方案,您可以在信息更丰富的模式上进行模式匹配(如 Willem Van Onsem 所建议):
case config of
Just (ProjectConfig {name=n}) -> putStrLn n
这将消除歧义,因为name
仅在 之后的模式中使用ProjectConfig
,因此可以接受。
另一种更麻烦的替代方法是使用自定义类型类。假设所有name
字段都是字符串,我们可以使用:
class HasName a where
getName :: a -> String
instance HasName ProjectConfig where
getName = name
instance HasName Other where -- for other types having the same field
getName = name
config :: IO ()
config = do
config <- resolveProjectConfig
case config of
Just c -> putStrLn (getName c)
...
(为什么这不是在后台自动完成的,我无法理解。)
推荐阅读
- javascript - 有没有办法检测控制台用户是否正在更改变量
- javascript - 如何使用 Javascript 为多个 id 使用函数
- reactjs - 反应原生文本输入;按下“完成”时触发事件
- jboss - jbpm持久化到Mysql外部数据库
- java - 无法覆盖 apache camel 中处理器之间的 bean 属性
- css - Flex justify-content, align-items 在 Safari 或移动浏览器上不起作用
- git - git错误:致命:身份验证失败
- python - Python3 socket.recv 没有确认
- angular - 希望使用材料设计在 Angular 8 中使用动态网格
- c++ - 如何在 Windows 中增加 CPP 的堆栈空间?