由于模式变量

时间:2017-08-09 12:07:57

标签: purescript

使用命名整个case表达式的模式变量,可以正确编译和错误“为表达式推断出无限类型”。以下编译正确:

m = case Left "anything" of
  e@(Left err) -> Left err
  (Right f) -> case lookup "key" f of
    Nothing -> Left "something else"
    (Just x) -> Right x

但是,如果我们使用模式变量e(用e代替“Left err”,功能相同),编译器会标记错误:

m = case Left "anything" of
  e@(Left err) -> e
  (Right f) -> case lookup "key" f of
    Nothing -> Left "something else"
    (Just x) -> Right x

“为表达式推断出无限类型:StrMap t1尝试将类型t1与StrMap t1类型匹配,同时检查表达式大小写((lookup”key“)f)...

我知道将StrMap t1与t1匹配是有问题的。我不明白为什么会这样。此外,在我的原始代码中,消息根本没有引用无限类型。以下是相关摘录:

retrieveDomeinResourceDefinition :: forall e.
  ResourceId
  -> Namespace
  -> (AsyncDomeinFile e (Either String PropDefs))
retrieveDomeinResourceDefinition id ns = do
  df <- retrieveDomeinFile (namespaceToDomeinFileName ns)
  case df of
    e@(Left err) -> pure $ e
    (Right f) -> case lookup id f of
      Nothing -> pure $ Left ("retrieveDomeinResourceDefinition: cannot find definition of " <> id <> " in DomeinFile for " <> ns)
      (Just propDefs) -> pure (Right propDefs)

retrieveDomeinFile :: forall e. Namespace -> AsyncDomeinFile e (Either String DomeinFile)

newtype PropDefs = PropDefs (StrMap Json)

现在,编译器告诉我:“无法匹配类型:具有StrMap类型的PropDefs PropDefs ...”看起来好像编译器没有注意到查找表达式。事实上,当我用“pure(Right f)”替换“pure(Right propDefs)”时,错误消失了(另一个出现在绑定df的行上,我明白了。)

现在我写这个我注意到'尝试匹配类型t1与类型StrMap t1'和'无法匹配类型:PropDefs与StrMap PropDefs'之间的相似性。不过,我不明白为什么使用e引入了这个问题。

1 个答案:

答案 0 :(得分:2)

使用模式匹配的那种方式可能在功能上是等价的,但类型不是 - 类型系统没有证据可以忽略Right的类型变量。

使用第二个示例中的类型 - 当您模式匹配e@(Left err)时,e的类型将为Either String DomeinFile - 但您需要Either String PropDefs。模式匹配不会“释放”右侧的类型变量,这就是为什么你必须重新构造带有错误的Left