{-# 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 是一个 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)
    ...

(为什么这不是在引擎盖下自动完成的,这超出了我的理解。)

关于haskell - 为什么 GHC 不能确定在这个 case 语句中使用哪个字段?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/57181359/

10-14 12:10
查看更多