首页 > 解决方案 > 在模式同义词中调用函数

问题描述

我在拉链上实现了一些功能,其中孔类型是存在量化的,即我有这样的东西:

data Zipper (c :: Type -> Constraint) ... =
  forall hole. (c hole, ...) =>
    Zipper hole ...

其中点表示我认为与我的问题无关的实现细节。现在考虑一些数据类型:

data Tree = Fork Tree Tree | Leaf Int

我想要的是能够检查我在树中的位置。在简单递归的情况下,实现此目的的标准方法是模式匹配:

case hole of
  Fork _ _ -> doSomething
  Leaf _   -> doSomethingElse

然而,洞的类型是存在量化的,所以简单的模式匹配是行不通的。我的想法是使用类型类

class WhereAmI p a where
    position :: a -> p a

data Position :: Type -> Type where
    C_Leaf :: Position Tree
    C_Fork :: Position Tree
    -- possibly more constructors if we're traversing
    -- multiple data structures

然后我可以做类似的事情

f :: Zipper (WhereAmI Position) Tree -> Int
f (Zipper hole _) = case position hole of
  C_Leaf -> let (Leaf x) = hole in x
  otherwise -> ...

然而,我想要的是使用类似这样的魔法来替换C_Leafat @"Leaf"即使用原始构造函数名称)

class WhereAmI' p (a :: Symbol) where
  position' :: Proxy a -> p

instance WhereAmI' (Position Tree) "Leaf" where
  position' _ = C_Leaf

instance WhereAmI' (Position Tree) "Fork" where
  position' _ = C_Fork

at :: forall a p. WhereAmI' p a => p
at = position (Proxy :: Proxy a)

这甚至可以工作,除了我不能at用作模式,如果我尝试将其设为模式,GHC 会抱怨模式中的解析错误......

有没有一些聪明的方法来实现我在这里描述的内容?

标签: haskell

解决方案



推荐阅读