Haskell Sigma中的限制类型
我的typeHaskell Sigma中的限制类型,haskell,dependent-type,singleton-type,Haskell,Dependent Type,Singleton Type,我的typeX按种类S编制索引,其中有几个函数可用于X。例如,f将xs1转换为xs2(但在这个简化示例中,它不使用xs1) 现在我想定义一些函数,这些函数可能返回xs2或xs3,具体取决于它的参数。简单的方法是使用或 g1 :: Bool -> X S1 -> Either (X S2) (X S3) g1 True x = Left X g1 False x = Right X 但我不想采用这种方法,因为当函数返回更多类型时,我需要嵌套或s 另一种方法是像这样使用Sigma g2
X
按种类S
编制索引,其中有几个函数可用于X
。例如,f
将xs1
转换为xs2
(但在这个简化示例中,它不使用xs1
)
现在我想定义一些函数,这些函数可能返回xs2
或xs3
,具体取决于它的参数。简单的方法是使用或
g1 :: Bool -> X S1 -> Either (X S2) (X S3)
g1 True x = Left X
g1 False x = Right X
但我不想采用这种方法,因为当函数返回更多类型时,我需要嵌套或s
另一种方法是像这样使用Sigma
g2 :: Bool -> X S1 -> Sigma S (TyCon X)
g2 True x = SS2 :&: X
g2 False x = SS3 :&: X
但这并不表示g2
只返回xs2
或xs3
。我可以通过在X
周围引入一个包装器来表达这个想法
data Y (s :: S) where
Y2 :: X S2 -> Y S2
Y3 :: X S3 -> Y S3
singletons [d|
type Z s = Y s
|]
g3 :: Bool -> X S1 -> Sigma S ZSym0
g3 True x = SS2 :&: Y2 X
g3 False x = SS3 :&: Y3 X
但是为每个组合定义这些包装并在调用方站点上展开它们是很麻烦的。如果我可以使用g2
方法直接限制类型就好了,例如,通过应用类型约束,但我不确定如何才能做到
如何使用g2
方法直接限制类型
我将GHC 8.8.4与一起使用。这个问题看起来过于简单和做作;如果有更具体的动机就好了。但这是一个黑暗中的镜头
我们可以在第一个组件上使用谓词定义Sigma
的变体:
datasigmap(i::Type)(p::i~>Constraint)(f::i->Type)其中
(:&?:::(p@@x)=>Sing x->f x->SigmaP i p f
一些定义谓词的代码似乎不可避免:
data Y23::S~>约束
类型实例应用Y23 x=Y23_x
类型族Y23_x(x::S)::约束,其中
Y23_uS2=(()::约束)
Y23_uS3=(()::约束)
Y23_uuu=('True~'False)
但是现在我们可以使用X
:
g3::Bool->xs1->SigmaP S Y23 X
g3真x=SS2:&?:x
g3假x=SS3:&?:x
另一种方法灵感来自。它类似于,但使用显式类型列表
{-# LANGUAGE DataKinds, GADTs, EmptyCase, InstanceSigs, PolyKinds, ScopedTypeVariables, TemplateHaskell, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-}
import Data.Kind
import Data.Singletons
import Data.Singletons.Prelude
import Data.Singletons.TH
singletons [d|
data S = S1 | S2 | S3 | S4 deriving (Show, Eq)
|]
data X (s :: S) = X
data SigmaL (l :: [s :: Type]) (t :: s ~> Type) where
(:&!:) :: OneOf fst l => Sing (fst :: s) -> t @@ fst -> SigmaL l t
type family OneOf s l :: Constraint where
OneOf s l = If (Elem s l) (() :: Constraint) ('True ~ 'False)
g5 :: Bool -> X S1 -> SigmaL '[S2, S3] (TyCon X)
g5 True x = SS2 :&!: X
g5 False x = SS3 :&!: X
使用类型列表,g::Bool->xs1->OneOf'[xs2,xs3]
,对OneOf
进行适当的定义怎么样?@luqui谢谢。我会试着写它,但如果你能给我一些关于这种实现的参考,我将不胜感激。谢谢。这是我脑子里想的东西,但我不知道怎么写。尽管我仍然需要为每种组合编写Y23
和Y23
,但我更喜欢这样而不是我的g3
。
{-# LANGUAGE DataKinds, GADTs, EmptyCase, InstanceSigs, PolyKinds, ScopedTypeVariables, TemplateHaskell, TypeApplications, TypeFamilies, TypeOperators, UndecidableInstances #-}
import Data.Kind
import Data.Singletons
import Data.Singletons.Prelude
import Data.Singletons.TH
singletons [d|
data S = S1 | S2 | S3 | S4 deriving (Show, Eq)
|]
data X (s :: S) = X
data SigmaL (l :: [s :: Type]) (t :: s ~> Type) where
(:&!:) :: OneOf fst l => Sing (fst :: s) -> t @@ fst -> SigmaL l t
type family OneOf s l :: Constraint where
OneOf s l = If (Elem s l) (() :: Constraint) ('True ~ 'False)
g5 :: Bool -> X S1 -> SigmaL '[S2, S3] (TyCon X)
g5 True x = SS2 :&!: X
g5 False x = SS3 :&!: X