我有一个非常简单的延续函数(为简单起见避免使用Monads):
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) = ...
我在这里忽略了一个基本的解决方案吗?我是继续学习的新手,所以我可能只是忽略了一些简单的事情。
答案 0 :(得分:1)
首先,您不能使用::
作为谓词来测试运行时类型(据我所知)。您的a
Gadt
参数完全是幽灵。这是有意的吗? example
可以是统一处理不同类型的多态,也可以是class
(parametric 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 ...
这仍然是伪代码,因为它没什么意义,但至少对我进行了类型检查。
答案 1 :(得分:0)
我根据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
数据结构中,可以实现基于类型的特定实现。