Haskell:“绑定位置中的合格名称”错误与Map.empty

时间:2018-04-15 18:48:56

标签: haskell newtype pattern-synonyms

我正在尝试使用空地图为新类型创建模式同义词。

{-# 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

编译时出现错误,说“绑定位置的合格名称:Map.empty”。我相信“Map.empty”应该属于我在newtype中声明的“Map.Map Int String”类型。

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

我将不胜感激任何反馈。

1 个答案:

答案 0 :(得分:3)

背景

  

因此,您无法像对待列表一样对地图进行模式匹配。

那是对的。 Data.Map.Mapabstract data type,意味着它的表示是隐藏的。在Haskell中,这意味着它的构造函数不会被导出。您无法编写检查Mapbalanced binary search tree的代码(并且您无论如何也不想) - 您必须使用模块&#39来完成其公共界面; s导出函数来创建,查询和操作Map s。

存在模式同义词以弥合ADT编程与方程左边的模式匹配的方便语法之间的差距。您可以将一些智能模式定义为模块API的一部分,而无需将ADT的实现与这些模式相结合。

您的问题

你得到那个错误,因为在语法上,模式同义词的右边必须是一个模式,而不是一个表达式。模式(通常)是应用于某些变量绑定器的值构造函数的名称 - 也就是说,在

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

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

所以我认为除了语法错误(Map.empty不是本地变量的有效名称,这就是为什么你会得到这个错误)你也是合乎逻辑的一个 - 无论如何,你无法在那个位置引用Map.empty

修复

正如我在my comment中建议的那样,您可以使用explicitly bidirectional pattern synonym来修补代码。这是一个简洁的功能,它允许您为模式同义词赋予不同的含义,具体取决于它是用作模式(即在模式上下文中)还是作为值构造函数(即在表达式上下文中)。

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

在第一行中,我定义EmptyStore在用作模式时的含义。 Map.null -> True语法称为视图模式 - 它表示&#34;将函数Map.null应用于此模式的一部分,并将其结果与{{1}匹配}&#34 ;.因此,当True中的EmptyStore为空时,StoreEnv会与Map匹配。

第二行定义StoreEnv用作表达式时的作用。它表示EmptyStore表达式是表达式EmptyStore的同义词 - &#34;创建一个空的StoreEnv Map.empty并将其包装在Map&#34;。< / p>

取消修复

但我提交StoreEnv的模式同义词API并不合理。为了使用,您应该真正定义完整的模式集,以便用户可以解构任何类型的Map。空案例很容易处理,因为只有一个空Map,但在非空Map上模式匹配意味着什么? Map并不意味着订购容器 - 没有&#34;首先和休息&#34;就像Map一样,所以这没有意义:

[]

您可以改为尝试定义在地图中存在特定键时匹配的模式:

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

但这不是有效的Haskell(pattern Contains k v <- (lookup k -> Just v) 正在引用,当它应该绑定时)。即使你能想出一种聪明的方式来表达它,这样的一组模式也一定是不完整的,因为你不能为每一个可能的密钥编写条款。

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