我想知道g
的适当类型签名是什么。我目前得到的那个不编译。我认为某处需要forall.
,但我不确定在哪里。
{-# LANGUAGE TypeFamilies #-}
import Control.Monad.ST (ST, runST)
data D
class C t where
type M t :: * -> *
f :: t -> M t D
g :: (C t, M t ~ ST s) => t -> D
g x = runST (f x)
main = return ()
(在回应@cirdec的评论时添加了示例)
{-# LANGUAGE TypeFamilies #-}
import Control.Monad.ST (ST, runST)
data D = D
class C t where
type M t :: * -> *
f :: t -> M t D
data T (m :: (* -> *)) = T
instance (Monad m) => C (T m) where
type M (T m) = m
f _ = return D
main = const (return ()) (runST (f T))
然后我用以下内容替换main
:
g x = runST (f x)
main = const (return ()) (g T)
根据它的外观,这应按照g T == runST (f T)
的定义编译为g
。但事实并非如此。我认为g
需要签名,但我不确定它是什么。
(添加了@cirdec评论的背景)
基本上在我的代码中C
是一类数据类型,可以被视为monadic disjoint Int
sets(我知道hackage上已有包但我的方法还有一些功能)。 C
具有union
和find
等函数。这些函数的实际实现取决于用户是否在创建时知道其大小或是否需要动态增长,因此类型类。但是,一旦创建了这些数据类型,就可以粗略地对待它们。所有这些都发生在monad代码中,通常是ST
或IO
,但技术上MonadRef中的任何内容都足够了。然后C
具有结果类型freeze
的函数M t D
,其中D
是某种结果数据类型。例如,对于IO,冻结的类型为(C t) => t -> IO D
,但ST
freeze
的内容更像(C t) => t -> ST s D
。在后一种情况下,应该能够在runST
的结果上运行freeze
来获取原始结果数据。
答案 0 :(得分:2)
以下文件为我编译:
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE PolyKinds #-}
import Control.Monad.ST (ST, runST)
data D = D
class C t where
type M t :: * -> *
f :: t -> M t D
data T (m :: (* -> *)) = T
instance (Monad m) => C (T m) where
type M (T m) = m
f _ = return D
data Equal a b where Refl :: Equal a a
convert :: Equal f g -> f a -> g a
convert Refl v = v
data Box s where
Box :: C t => Equal (M t) (ST s) -> t -> Box s
g :: (forall s. Box s) -> D
g box = runST (case box of Box eq x -> convert eq (f x))
main = const (return ()) (g (Box Refl T))