基于输入类型的延续函数实现?

Continuation function implementations based upon input type?

我有一个非常简单的延续函数(为简单起见避免使用 Monad):

data C a = C {unwrap :: (a -> a) -> a}

本质上,我试图根据输入类型执行不同的实现,类似于 (sudo-code):

data Gadt a where
  AString :: String -> Gadt Bool
  AInt :: Int -> Gadt Bool

data C a = C {unwrap :: (a -> Gadt a) -> a}

example :: a -> C a
example v = C $ \f -> | (v :: Int) == True      = f (AInt v)
                      | (v :: String) == True   = f (AString v)

cont :: Gadt a -> a
cont (AInt v)       = ...
cont (AString v)    = ...

我是否忽略了这里的基本解决方案?我是 continuation 的新手,所以我可能只是忽略了一些简单的事情。

首先你不能使用::作为测试运行时类型的谓词(据我所知)。其次,Gadta 参数完全是幻影。这是故意的吗? example 可以通过统一处理不同类型来实现多态,或者您需要使用 classparametric vs ad-hoc 多态)。你可能想要像

这样的东西
data Gadt where
    AInt :: Int -> Gadt
    AString :: String -> Gadt

data C a = C { unwrap :: (a -> Gadt) -> Gadt }

class Ex a where
    example :: a -> C a

instance Ex Int where
    example v = C ...

instance Ex String where
    example v = C ...

这仍然是伪代码,因为它没有什么意义,但至少对我来说是类型检查。

根据 here 的建议,我找到了一个可能的解决方案:

newtype C r a = C {runC :: (a -> r) -> r}

data Hole = Hole1 Int | Hole2 String | Hole3 Bool

example :: String -> C Bool a
example s = C $ \f -> do
   x <- f (Hole1 22)
   y <- f (Hole2 "string")
   k (Hole3 False)

cont :: Hole -> Bool
cont (Hole1 x) = ...
cont (Hole2 x) = ...
cont (Hole3 x) = ...

这通过将输入类型包装在 Hole 数据结构中来启用基于类型的特定实现。