Haskell 存在类型。为异构映射编写类实例
使用以下类型和类定义,我不理解为什么在创建下面的Haskell 存在类型。为异构映射编写类实例,haskell,existential-type,Haskell,Existential Type,使用以下类型和类定义,我不理解为什么在创建下面的实例时会出现错误 我需要MyMap来保存异构值的映射 {-# LANGUAGE ExistentialQuantification #-} module Scratch.SO_ExtistentialTypes where import Data.Map type MyMap a = Map String a class MyClass c where getMyMap :: forall a. c -> MyMap a d
实例时会出现错误
我需要MyMap来保存异构值的映射
{-# LANGUAGE ExistentialQuantification #-}
module Scratch.SO_ExtistentialTypes where
import Data.Map
type MyMap a = Map String a
class MyClass c where
getMyMap :: forall a. c -> MyMap a
data MyData = forall a. MyData {
myMap :: MyMap a
}
instance MyClass MyData where
getMyMap = myMap -- <= ERROR
{-#语言存在量化}
模块Scratch.SO_ExtistentialTypes,其中
导入数据。映射
键入MyMap a=映射字符串a
我的c班在哪里
getMyMap::对于所有a。c->MyMap a
数据MyData=对于所有a。我的数据{
myMap::myMap a
}
实例MyClass MyData,其中
getMyMap=myMap--首先,这里的For all
是多余的:
class MyClass c where
getMyMap :: forall a. c -> MyMap a
没有显式绑定的类型变量通常在最外层进行量化,因此这与justc->MyMap a
完全相同
除此之外,普遍量化的类型肯定不会与存在量化的类型相匹配。getMyMap
的类型表示,给定一个c
类型的值,它将为任何可能的a
类型选择生成一个MyMap a
类型的值。另一方面,访问器myMap
表示,给定类型MyData
的值,它将为某些特定但未知的类型a
生成类型myMap a
的值
不可能让未包装的存在类型自行浮动(这需要一个与所有
对应的exists
量词),因此无法重写getMyMap
的类型,从而使myMap
是一个有效的实现
对于具有存在类型的对象,您所能做的就是将其包装到另一个隐藏存在量词的数据类型中,或者将其提供给具有通用量化类型的参数的函数。例如,您可以将列表[a]
上的length
与a
一个存在类型一起使用
在您的例子中,Map
的值具有存在类型,没有其他结构或约束,因此它们几乎没有任何用处,也可能是()
,首先,这里的对于所有
都是多余的:
class MyClass c where
getMyMap :: forall a. c -> MyMap a
没有显式绑定的类型变量通常在最外层进行量化,因此这与justc->MyMap a
完全相同
除此之外,普遍量化的类型肯定不会与存在量化的类型相匹配。getMyMap
的类型表示,给定一个c
类型的值,它将为任何可能的a
类型选择生成一个MyMap a
类型的值。另一方面,访问器myMap
表示,给定类型MyData
的值,它将为某些特定但未知的类型a
生成类型myMap a
的值
不可能让未包装的存在类型自行浮动(这需要一个与所有
对应的exists
量词),因此无法重写getMyMap
的类型,从而使myMap
是一个有效的实现
对于具有存在类型的对象,您所能做的就是将其包装到另一个隐藏存在量词的数据类型中,或者将其提供给具有通用量化类型的参数的函数。例如,您可以将列表[a]
上的length
与a
一个存在类型一起使用
在您的例子中,Map
的值具有存在类型,没有其他结构或约束,因此它们几乎毫无用处,也可能是()
,您在这里试图实现什么?因为我非常怀疑这是一个好的方法。@C.a.McCann类型和类是定义“API”的模块的一部分。数据
和类型
是(简化的)暂定实现。@C.A.McCann另一种说法是:如何创建一个可以成为MyClass实例的数据类型(MyData),getMyMap
唯一合理的定义是忽略其输入并每次返回一个空的Map
。我假设这不是您想要的,因此您可能需要重新思考MyClass
的用途。在类型化设置中,有一个更严格的异构映射概念是有意义的,其中值的类型取决于键的索引。您可能有数据映射(k::*->*)=…
,然后您会有一个类似查找::ord1k=>映射k->ka->a的函数。现在,如果将参数实例化为Map
到一个细化其索引的GADT,则可以将不同的键映射到不同的值类型。我不久前写了一本,但现在找不到。也许这会帮你弄清楚你想要什么。你想在这里实现什么?因为我非常怀疑这是一个好的方法。@C.a.McCann类型和类是定义“API”的模块的一部分。数据
和类型
是(简化的)暂定实现。@C.A.McCann另一种说法是:如何创建一个可以成为MyClass实例的数据类型(MyData),getMyMap
唯一合理的定义是忽略其输入并每次返回一个空的Map
。我假设这不是您想要的,因此您可能需要重新思考MyClass
的用途。在类型化设置中,有一个更严格的异构映射概念是有意义的,其中值的类型取决于键的索引。您可能有数据映射(k::*->*)=…
,然后您会有一个类似查找::ord1k=>映射k->ka->a的函数。现在,如果将参数实例化为Map
到一个GADT,该GADT细化了它的索引,那么可以使用不同的