首页 > 解决方案 > 为什么 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 cc 是 a ProjectConfig,但是在putStrLn (name c)我得到错误“不明确的出现名称。它可以引用字段名称... [具有名称字段的其他内容列表]”。

当然,如果它知道是什么c,它应该能够选择正确的名称功能吗?有没有办法让它弄清楚,而不添加c :: ProjectConfig

标签: haskell

解决方案


这是 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)
    ...

(为什么这不是在后台自动完成的,我无法理解。)


推荐阅读