Haskell 用数据族替换单例数据类型
因此,在我当前的项目中,我发现自己正在使用单例类型进行一系列类型级逻辑 例如:Haskell 用数据族替换单例数据类型,haskell,dependent-type,type-families,Haskell,Dependent Type,Type Families,因此,在我当前的项目中,我发现自己正在使用单例类型进行一系列类型级逻辑 例如: {-# LANGUAGE DataKinds #-} {-# LANGUAGE KindSignatures #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE GADTs #-} module TypeBools where type family (||) (a :: Bool) (b :: Bool) ::
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GADTs #-}
module TypeBools where
type family (||) (a :: Bool) (b :: Bool) :: Bool where
'False || 'False = 'False
'False || 'True = 'True
'True || 'False = 'True
'True || 'True = 'True
data OrProof (a :: Bool) (b :: Bool) (c :: Bool) where
OrProof :: SBool (a || b) -> OrProof a b (a || b)
data SBool (b :: Bool) where
SFalse :: SBool 'False
STrue :: SBool 'True
class Boolean b where
sBool :: SBool b
instance Boolean 'False where
sBool = SFalse
instance Boolean 'True where
sBool = STrue
orProof :: (Boolean a, Boolean b) => OrProof a b (a || b)
orProof = go sBool sBool where
go :: SBool a -> SBool b -> OrProof a b (a || b)
go SFalse SFalse = OrProof SFalse
go SFalse STrue = OrProof STrue
go STrue SFalse = OrProof STrue
go STrue STrue = OrProof STrue
这对我来说很有效。我喜欢不必在街上兜圈子
单例类型手动,能够在必要时通过typeclass调用它们
e、 上面的布尔类,但这导致了一系列相当类似的
仅用于将类型具体化为单例数据的类型类
我想也许我可以把多个类型类抽象成一个类型族,
例如,将上面的SBool和Boolean替换为:
{-# LANGUAGE PolyKinds #-}
{-# LANGUAGE ConstraintKinds #-}
-- ...
class Singleton (t :: k) where
data Sing t
sing :: Sing t
instance Singleton 'False where
data Sing 'False = SFalse
sing = SFalse
instance Singleton 'True where
data Sing 'True = STrue
sing = STrue
type SBool b = Sing (b :: Bool)
type Boolean b = Singleton (b :: Bool)
sBool :: Boolean b => SBool b
sBool = sing
但是我得到了模式匹配错误:
TypeBools2.hs:42:13:
Couldn't match type ‘b1’ with ‘'True’
‘b1’ is a rigid type variable bound by
the type signature for
go :: SBool a1 -> SBool b1 -> OrProof a1 b1 (a1 || b1)
at TypeBools2.hs:40:9
Expected type: SBool b1
Actual type: Sing 'True
Relevant bindings include
go :: SBool a1 -> SBool b1 -> OrProof a1 b1 (a1 || b1)
(bound at TypeBools2.hs:41:3)
In the pattern: STrue
In an equation for ‘go’: go SFalse STrue = OrProof STrue
In an equation for ‘orProof’:
orProof
= go sBool sBool
where
go :: SBool a -> SBool b -> OrProof a b (a || b)
go SFalse SFalse = OrProof SFalse
go SFalse STrue = OrProof STrue
go STrue SFalse = OrProof STrue
go STrue STrue = OrProof STrue
我不确定是否还有其他东西可以说服编译器
b1应该有一个好样的布尔,或者如果我只是在这里找错了树。你要求的功能和更多功能可以在中找到。很长一段时间以来,它一直是类型级编程的最终模板。您应该使用它或复制实现。无论如何,我会在这里做一个简单的单例解决方案展示 模式匹配不起作用,因为STrue和SFalse位于不同的数据定义中,而这些数据定义一开始就不是GADT。模式匹配仅在正确的GADT-s上完成时细化类型。我们需要对种类进行分派,以便能够将同一种类的所有单例构造函数组合在一起 我们可以使用适当的类或顶级数据族来实现这一点。对于我们现在的目的来说,后者更简单,所以让我们这样做:
data family Sing (x :: k)
data instance Sing (b :: Bool) where
STrue :: Sing True
SFalse :: Sing False
对于sing,我们不需要进行实物分派,因为我们只使用它来获取特定的提升值,因此以下方法有效:
class SingI (x :: k) where
sing :: Sing x
instance SingI True where sing = STrue
instance SingI False where sing = SFalse
至于orporoof,我们想要的是类型级别| |的单例,它最直接地通过以下类型完成:Sing b1->Sing b2->Sing b1 | | b2。我们将根据象形文字单件命名惯例,将其命名为%:| |
type family (:||) (b1 :: Bool) (b2 :: Bool) :: Bool where
True :|| b = True
False :|| b = b
(%:||) :: Sing b1 -> Sing b2 -> Sing (b1 :|| b2)
(%:||) STrue b2 = STrue
(%:||) SFalse b2 = b2
OrProof并不是很有用,因为它只是一种特殊的等式类型以及SingI约束或简单的SingC:
您所要求的功能和更多功能可以在中找到。很长一段时间以来,它一直是类型级编程的最终模板。您应该使用它或复制实现。无论如何,我会在这里做一个简单的单例解决方案展示 模式匹配不起作用,因为STrue和SFalse位于不同的数据定义中,而这些数据定义一开始就不是GADT。模式匹配仅在正确的GADT-s上完成时细化类型。我们需要对种类进行分派,以便能够将同一种类的所有单例构造函数组合在一起 我们可以使用适当的类或顶级数据族来实现这一点。对于我们现在的目的来说,后者更简单,所以让我们这样做:
data family Sing (x :: k)
data instance Sing (b :: Bool) where
STrue :: Sing True
SFalse :: Sing False
对于sing,我们不需要进行实物分派,因为我们只使用它来获取特定的提升值,因此以下方法有效:
class SingI (x :: k) where
sing :: Sing x
instance SingI True where sing = STrue
instance SingI False where sing = SFalse
至于orporoof,我们想要的是类型级别| |的单例,它最直接地通过以下类型完成:Sing b1->Sing b2->Sing b1 | | b2。我们将根据象形文字单件命名惯例,将其命名为%:| |
type family (:||) (b1 :: Bool) (b2 :: Bool) :: Bool where
True :|| b = True
False :|| b = b
(%:||) :: Sing b1 -> Sing b2 -> Sing (b1 :|| b2)
(%:||) STrue b2 = STrue
(%:||) SFalse b2 = b2
OrProof并不是很有用,因为它只是一种特殊的等式类型以及SingI约束或简单的SingC:
我可以问一下你的| |为什么不短路吗?我希望使用'False | | x=x;'可以得到更好的减少例如,True | | x='True。你应该直接使用它,但如果你不打算使用它,你应该看看它们是如何做的,并复制它,因为它们正是你想要的。特别是,您需要一个非关联的数据族数据族Sing t::k;类Singleton t::k where sing::sing t和数据实例sing b::Bool where…dfeuer:它可以。不过,这是问题的另一个方面。而且,我很难理解你的orporite和orporite应该表达什么。他们似乎有点。。。迂回的我知道这与你的问题没有直接关系。德弗尔:这是一个问题的简化示例,但它允许你进行类型级逻辑,而不用担心GHC pre8无法通过围绕参数进行推理来推断内射性。例如,or::Boolean a,Boolean b=>SBool a | | b;or=case或orProof of orProof c->c给出了旧的NB:“| |”是一个类型函数,可能不是内射模糊错误。请问为什么您的| |没有短路?我希望使用'False | | x=x;'可以得到更好的减少例如,True | | x='True。你应该直接使用它,但如果你不打算使用它,你应该看看它们是如何做的,并复制它,因为它们正是你想要的。特别是,您需要一个非关联的数据族数据族Sing t::k;类Singleton t::k where sing::sing t和数据实例sing b::Bool where…dfeuer:它可以。不过,这是问题的另一个方面。而且,我很难理解你的orporite和orporite应该表达什么。看起来有点像。
.. 迂回的我知道这与你的问题没有直接关系。德弗尔:这是一个问题的简化示例,但它允许你进行类型级逻辑,而不用担心GHC pre8无法通过围绕参数进行推理来推断内射性。例如,or::Boolean a,Boolean b=>SBool a | | b;or=case orProof of orProof c->c给出了旧的NB:“| |”是一个类型函数,可能不是内射模糊错误。Singleton几乎拥有当前GHC中所有人类可能的功能。这并不简单,所以如果您有问题,请随时提出进一步的问题。我在这个网站上也有很多关于单身汉的答案,你可能会想知道。单身汉几乎拥有当前GHC所能提供的一切。这并不简单,所以如果您有问题,请随时提出进一步的问题。我在这个网站上也有一些与单身相关的答案,你可能会想知道。