结合Data.Dynamic和类型类

时间:2014-04-05 03:50:42

标签: haskell dynamic typeclass

给定Dynamic类型的变量,可以利用内部变量的类型类而不调整确切的类型?例如,假设我想写一个函数prettyShow。如果内部类型是Show的实例,那么我们应该使用该实例;否则,我们应该使用Dynamic类的实例。在代码中,这可能如下所示:

prettyShow :: Dynamic -> String
prettyShow x = case fromDynamic x :: (forall a. Show a => Maybe a) of
    Nothing -> show x
    Just y -> show y

编辑:由于看起来无法直接完成,可以采取哪些好的解决方法?

1 个答案:

答案 0 :(得分:6)

这可以使用open-typerep库中Dynamic的实现来完成(如果您接受使用泛型编程和大量GHC扩展)。

{-# LANGUAGE TypeOperators #-}

import Data.TypeRep

type Types = BoolType :+: IntType :+: ListType

x, y :: Dynamic Types
x = toDyn [False,True]
y = toDyn [1, 2 :: Int]

test1 = show x
test2 = show y

show的定义很简单,您可以使用该库来定义动态值上的其他函数。

在上面的例子中,我使用了封闭式宇宙Type。但是,使用数据类型单点技巧,您还可以定义开放Universe的功能。例如,show本身是开放的。

<强>性能

simple benchmark表示,对于上面使用的小型Universe,此DynamicData.Dynamic中的base慢2-3倍。将Universe增加到30个类型构造函数会使它慢一点多10倍。

自动推导新类型

open-typerep支持从少量预定义表示类型中创建Universe。原则上应该可以使用TemplateHaskell自动派生新类型的表示,但为WitnessPWitness生成正确的实例将会很棘手,因为这些实例取决于可用的其他实例。 (例如Witness Show实例使用了Dynamic