haskell - 没有存在类型的异构索引结构?

标签 haskell existential-type

我正在尝试构建异构索引结构并提出以下解决方案,但 I was told not to use existential types .

你能看到更好的解决方案吗?

我想保持接口(interface)定义(typeclass)和具体实现(datainstance)之间的分离。 编辑 遵循@hammar 的评论:在实际应用中,值不是Show n 但只是存储了一个查询;还有myData附加记录更复杂。

如果这可以带来更好的解决方案,那么确切的要求是构建 map 的 map (内部 map )。每个内部图都是同质的,形式为 Map String a但是,每个内部映射都可能对其值强制使用不同的类型。您也可以将其视为两级索引结构。实现不必使用 Data.Map但必须高效。

{-# LANGUAGE ExistentialQuantification #-}
module Scratch.SO_ExtistentialTypes where

import Data.Map

data HeteroValue = forall a. Show a => HV a 

instance Show HeteroValue where
    show (HV b) = show b

type MyMap = Map String HeteroValue

class MyClass c where 
    getMyMap :: c -> MyMap

data MyData = MyData {
    myMap ::  MyMap
}

instance MyClass MyData where
    getMyMap = myMap

这个片段可以使用 ghci 运行
let myMap = fromList [("key1", HV "abc"), ("key2", HV 123)] :: MyMap
let myData = MyData myMap
getMyMap myData 

最佳答案

这是面向对象语言的一个很好的模式,但它是众所周知的 Haskell antipattern .
阅读那篇文章。我想让你读的比我说的任何其他内容都多。

另见 this answer ,但附带条件是我认为 GADT 比存在类型更优雅(见下文)。

请尝试找到编写程序的最佳函数式编程方式,而不是重新实现面向对象编程的最佳函数式编程方式。除了希望以 OO 风格进行编程之外,您还没有明确代码的任何目的。

(想象一下 Craig,一个刚接触 Java 的 C 程序员,他正试图找到如何创建指向结构数组的指针,或者在尝试创建具有 malloc 功能的方法时卡住,或者因为没有指针算法而感到沮丧。珍妮特Java 程序员会问克雷格为什么他想自己做指针,垃圾收集有什么问题,以及为什么在地球上有内置边界检查的数组时,为什么会有人想要指针算术?真的,克雷格会更好在决定他真的不能没有 C 的哪些特性之前先学习编程惯用的 Java。OO 与 C 的尽可能接近机器但仍然相对机器的范式不同独立哲学。Craig 应该优先学习新范式。这可能会让他成为一个更好的 C 程序员。不要去法国只说英语,看 CNN 和吃麦当劳!有一种感觉,你应该尝试写作你的代码以尽可能实用的方式。)

如果您真的不想获得关于您的数据的其他信息,而不是它遵守您的契约(Contract),那么一种方法是使用 GADT。您应该知道 Haskell 会要求您坚持 claim ;没有 Actor 可以让你摆脱一个轻率的设计决定。 (强制转换是一种将编译时检查转变为运行时检查的方法,或者换一种说法,一种将编译时错误转变为运行时错误的方法。我不认为这是一件好事。)

{-# LANGUAGE GADTs #-}

class Contract a where
   toString :: a -> String
   fromInts :: Int -> Int -> a
   alter :: a -> a
   -- other functionality

data Encapsulated where
   Encapsulate :: Contract a => a -> Encapsulated

现在,一旦你封装了你的数据,你可以对它做任何你喜欢的事情,就像它是一个普通的数据类型一样,并恢复任何 Contract像这样的编辑功能:
munged :: Encapsulated -> String
munged (Encapsulate a) = toString.alter.alter.alter $ a

如果你喜欢,你可以存储一大堆Encapsulated map 中的数据,无需做任何特殊或重新实现Data.Map为你的存在主义,因为,这里是强大的功能范式:Data.Map使没有对您的数据的任何假设。它是参数多态性,适用于任何事情。任何东西,甚至功能。它所做的唯一假设是您的键是可排序的 (Ord k =>) 并且您的数据是同质的(并且我们的 GADT 是同质的,尽管是由异构数据制成的)。

这是满足您要求的一种方式,但如果我们知道您想要它的目的,我们可以为您提供更好的建议。 (也许是另一个新问题!)请认真阅读我链接到的文章,看看您是否可以将您的类实现为一个充满函数/结果的数据类型,以及您的实例作为该数据类型的函数。

关于haskell - 没有存在类型的异构索引结构?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13097890/

相关文章:

haskell - 存在类型的类型变量引入

haskell - ‘Text.Regex.Posix’ 是否被重命名或替换?

Haskell 编译程序出现段错误

haskell - 为什么 GHC 不导入 Semigroup ((<>))

haskell - 如何在 Haskell 中声明抽象数据容器类型?

c++ - C++中存在量化的等价物?

haskell - 为什么 Debug.Trace 是邪恶的?

haskell - 用于分析 Haskell 程序性能的工具

java - Scala的存在类型和Java通配符的区别?

language-agnostic - 什么是存在类型?