使用命名整个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引入了这个问题。
答案 0 :(得分:2)
使用模式匹配的那种方式可能在功能上是等价的,但类型不是 - 类型系统没有证据可以忽略Right
的类型变量。
使用第二个示例中的类型 - 当您模式匹配e@(Left err)
时,e
的类型将为Either String DomeinFile
- 但您需要Either String PropDefs
。模式匹配不会“释放”右侧的类型变量,这就是为什么你必须重新构造带有错误的Left
。