Haskell:"Qualified name in binding position" 错误 Map.empty

Haskell: "Qualified name in binding position" error with Map.empty

我正在尝试为具有空映射的新类型创建模式同义词。

{-# Language PatternSynonyms #-}

import qualified Data.Map as Map

newtype StoreEnv = StoreEnv (Map.Map Int String)
   deriving (Eq, Show)

pattern EmptyStore :: StoreEnv
pattern EmptyStore = StoreEnv Map.empty

编译时出现 "Qualified name in binding position: Map.empty" 错误。我相信 "Map.empty" 应该属于我在 newtype.

中声明的类型 "Map.Map Int String"

我的问题是是否有办法正确地为空地图添加别名。

如果有任何反馈,我将不胜感激。

背景

So you cannot pattern match against maps like you would do with list then.

没错。 Data.Map.MapMap 中的一个 abstract data type, meaning that its representation is hidden. In Haskell that means its constructors aren't exported. You can't write code which inspects the balanced binary search tree(无论如何你都不想)——你必须通过它的 public 接口,使用模块的导出函数来创建, 查询和操作 Maps.

模式同义词的存在是为了弥合 ADT 编程与等式左侧模式匹配的便捷语法之间的差距。您可以将一些智能模式定义为模块 API 的一部分,而不必将 ADT 的实现与这些模式耦合。

你的问题

您收到该错误是因为从语法上讲,模式同义词的右侧必须是模式,而不是表达式。模式(通常)是应用于某些 变量绑定器 的值构造函数的名称 - 也就是说,在像

这样的定义中
getBar (Foo bar baz) = bar

左侧的 barbaz 定义了右侧范围内的变量。它们是新的绑定,而不是对某些外部范围中可能存在的任何 barbaz 变量的引用。

所以我认为除了语法错误(Map.empty 不是局部变量的有效名称,这就是你得到那个错误的原因)你也犯了一个合乎逻辑的错误 -无论如何,您都无法在该位置引用 Map.empty

修复

正如我在 , you can patch up your code by using an explicitly bidirectional pattern synonym 中所建议的那样。这是一个巧妙的功能,它允许您根据模式同义词是用作模式(即在模式上下文中)还是用作值构造函数(即在表达式上下文中)来赋予不同的含义。

pattern EmptyStore <- StoreEnv (Map.null -> True)
    where EmptyStore = StoreEnv Map.empty

在第一行中,我定义了 EmptyStore 用作模式时的含义。 Map.null -> True 语法称为 视图模式 - 它表示 "apply the function Map.null to this piece of the pattern, and match its result with True"。因此,当 StoreEnv 中的 Map 为空时,EmptyStore 匹配 StoreEnv

第二行定义 EmptyStore 用作表达式时的作用。它表示表达式 EmptyStore 是表达式 StoreEnv Map.empty - "create an empty Map and wrap it in a StoreEnv".

的同义词

未修复

但是我认为 Map 的模式同义词 API 没有任何意义。为了可用,您应该真正定义一组 完整 模式,以便用户可以解构任何类型的 Map。空的情况好办,因为只有一个空的Map,但是在非空的Map上进行模式匹配是什么意思呢? Maps 并不意味着要订购容器 - 没有像 [] 那样的 "first-and-rest",所以这没有意义:

pattern Cons k v rest <- {- what goes here? -}
    where Cons k v rest = insert k v rest

您可能会尝试定义一个模式,该模式在映射中存在特定键时匹配:

pattern Contains k v <- (lookup k -> Just v)

但这无效 Haskell(k 引用 ,而它应该被 绑定).即使你能想出一个巧妙的方式来表达它,这样的一组模式也必然是不完整的,因为你不能为每个可能的键都写出子句。

换句话说,我认为您不应该尝试为此数据类型定义模式同义词。坚持使用普通函数!