我有一个类型类,它强加class KnownNat (Card a) => HasFin a where
type Card a :: Nat
...
约束:
instance HasFin () where
type Card () = 1
...
instance HasFin Bool where
type Card Bool = 2
...
并且,我有几个基本"构建块"类型:
KnownNat
我计划建立许多"复合材料"使用总和和产品来排除这些构建块类型。目前,当我为这些复合类型之一实例HasFin
时,我必须明确地编写复合instance (HasFin a, HasFin b, KnownNat (Card a + Card b)) => HasFin (Either a b) where
type Card (Either a b) = Card a + Card b
...
约束:
KnownNat (Card a + Card b)
我真的希望不必须在上面的代码中编写:(HasFin a, HasFin b) =>
。
是否有任何类型检查器插件,可以自动从(KnownNat (Card a + Card b)) =>
推断到dependency:properties
?
如果不这样做,我可以写一个蕴涵,提供相同的推断吗?
答案 0 :(得分:3)
是的,有这样的插件! ghc-typelits-knownnat
使用示例:
-- Install ghc-typelits-knownnat via your favorite build tool like any other package
-- then only this line needs to be added to enable the plugin
{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}
-- Nothing special to be done otherwise, type-level programming as usual.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
module Card where
import GHC.TypeLits
class KnownNat (Card a) => HasFin a where
type Card a :: Nat
instance HasFin () where
type Card () = 1
instance (HasFin a, HasFin b) => HasFin (Either a b) where
type Card (Either a b) = Card a + Card b
这是使用constraints库的另一种没有插件的技术。它定义GADT以捕获约束和蕴涵作为价值级词典,并提供一些公理,包括(KnownNat a, KnownNat b) :- KnownNat (a + b)
蕴涵。
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeApplications #-}
module Card where
import Data.Constraint
import Data.Constraint.Nat
import GHC.TypeLits
class HasFin a where
type Card a :: Nat
card :: Dict (KnownNat (Card a))
instance HasFin () where
type Card () = 1
card = Dict
instance (HasFin a, HasFin b) => HasFin (Either a b) where
type Card (Either a b) = Card a + Card b
card =
case (card @a, card @b, plusNat @(Card a) @(Card b)) of
(Dict, Dict, Sub Dict) -> Dict