我最近一直在玩-XDataKinds
,并想采用类型族的提升结构构建并将其拉回价值水平。我相信这是可能的,因为组合组件非常简单,终端表达式也很简单。
背景
我想降级/反映简单的玫瑰树Strings
,它们成为一种类型Tree Symbol
(当GHC.TypeLits.Symbol
用作类型级字符串时)。这是我的样板代码:
{-# LANGUAGE DataKinds #-}
import GHC.TypeLits
import Data.Proxy
data Tree a = Node a [Tree a]
type TestInput = '[ 'Node "foo" '[ 'Node "bar" '[]
, 'Node "baz" '[]
]
, 'Node "bar" '[]
]
这是一个简单的类型级玫瑰森林,看起来像这个非常详细的图表:
*-- "foo" -- "bar"
| \_ "baz"
\_ "bar"
尝试的解决方案
理想情况下,我想遍历这个结构并将 1 对 1 映射回kind的值*
,但是由于重载而仍然保留(必要的)实例的同时如何异构地执行此操作并不是很明显。
vanila on#haskell
建议我使用类型类来绑定两个世界,但这似乎比我想象的要棘手。我的第一次尝试尝试通过实例头约束对类型级模式匹配的内容进行编码,但我的关联类型(用于编码*
映射的 -kinded 类型结果)重叠 - 显然实例头在某种程度上被 GHC 忽略了。
理想情况下,我还希望列表和树的反射是通用的,这似乎会导致问题 - 这就像使用类型类来组织类型/种类层。
这是我想要的一个非功能示例:
class Reflect (a :: k) where
type Result :: *
reflect :: Proxy a -> Result
class ReflectEmpty (empty :: [k]) where
reflectEmpty :: forall q. Proxy empty -> [q]
reflectEmpty _ = []
instance ReflectEmpty '[] where
instance ReflectEmpty a => Reflect a where
type Result = forall q. [q]
reflect = reflectEmpty
-- | The superclass constraint is where we get compositional
class Reflect (x :: k) => ReflectCons (cons :: [x]) where
reflectCons :: PostReflection x ~ c => Proxy cons -> [c]
instance ( Reflect x
, ReflectCons xs ) => ReflectCons (x ': xs) where
reflectCons _ = reflect (Proxy :: Proxy x) :
reflectCons (Proxy :: Proxy xs)
instance ( Reflect x
, ReflectEmpty e ) => ReflectCons (x ': e) where
reflectCons _ = reflect (Proxy :: Proxy x) :
reflectEmpty (Proxy :: Proxy e)
...
这段代码有几处通常是错误的。这是我看到的:
- 我需要某种形式的前瞻来了解泛型类型级列表反射的更高种类反射的结果 -
PostReflection
类型函数 - 我需要即时创建和销毁
Proxy
。我不确定这目前是否无法编译,但我不相信这些类型会像我期望的那样统一。
但是,这种类型类层次结构感觉像是捕获异构语法的唯一方法,所以这可能仍然是一个开始。对此的任何帮助都将是巨大的!