first-class-families 0.5.0.0 → 0.6.0.0
raw patch · 9 files changed
+116/−16 lines, 9 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
+ Fcf: data Case :: [Match j k] -> j -> Exp k
+ Fcf: data Match j k
+ Fcf: infix 0 -->
+ Fcf: type (-->) = ( 'Match_ :: j -> k -> Match j k)
+ Fcf: type Any = ( 'Any_ :: k -> Match j k)
+ Fcf: type Else = ( 'Else_ :: (j -> Exp k) -> Match j k)
+ Fcf: type Is = ( 'Is_ :: (j -> Exp Bool) -> k -> Match j k)
+ Fcf.Utils: data Case :: [Match j k] -> j -> Exp k
+ Fcf.Utils: data Match j k
+ Fcf.Utils: infix 0 -->
+ Fcf.Utils: type (-->) = ( 'Match_ :: j -> k -> Match j k)
+ Fcf.Utils: type Any = ( 'Any_ :: k -> Match j k)
+ Fcf.Utils: type Else = ( 'Else_ :: (j -> Exp k) -> Match j k)
+ Fcf.Utils: type Is = ( 'Is_ :: (j -> Exp Bool) -> k -> Match j k)
Files
- CHANGELOG.md +8/−2
- first-class-families.cabal +3/−3
- src/Fcf.hs +9/−0
- src/Fcf/Combinators.hs +4/−0
- src/Fcf/Data/Bool.hs +1/−0
- src/Fcf/Data/List.hs +0/−1
- src/Fcf/Data/Nat.hs +5/−0
- src/Fcf/Utils.hs +65/−2
- test/test.hs +21/−8
CHANGELOG.md view
@@ -1,11 +1,17 @@+# 0.6.0.0++- Add `Fcf.Utils.Case` and `(Fcf.Combinators.>>=)`+- Deprecate `Fcf.Bool.Guarded`+- GHC 8.8 compatibility+ # 0.5.0.0 - Modularized library - `Fcf.Utils`: - + Added `TError`- + Renamed `Collapse` to `Constraints`+ + Add `TError`+ + Rename `Collapse` to `Constraints` - `Fcf.Data.List`: Added `Cons`, `Last`, `Init`, `Elem`
first-class-families.cabal view
@@ -1,5 +1,5 @@ name: first-class-families-version: 0.5.0.0+version: 0.6.0.0 synopsis: First class type families description:@@ -18,7 +18,7 @@ extra-source-files: README.md, CHANGELOG.md cabal-version: >=1.10 tested-with:- GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.3, GHC == 8.6.1+ GHC == 8.0.2, GHC == 8.2.2, GHC == 8.4.4, GHC == 8.6.5, GHC == 8.8.1 library hs-source-dirs: src@@ -34,7 +34,7 @@ Fcf.Utils build-depends: -- This upper bound is conservative.- base >= 4.9 && < 4.13+ base >= 4.9 && < 4.14 ghc-options: -Wall default-language: Haskell2010
src/Fcf.hs view
@@ -110,6 +110,15 @@ , Guard((:=)) , Otherwise + -- ** Case splitting++ , Case+ , Match()+ , type (-->)+ , Is+ , Any+ , Else+ -- ** Nat , type (+)
src/Fcf/Combinators.hs view
@@ -29,6 +29,7 @@ -- ** Monadic operations +infixl 1 >>= infixr 1 =<<, <=< infixl 4 <$>, <*> @@ -46,6 +47,9 @@ data (=<<) :: (a -> Exp b) -> Exp a -> Exp b type instance Eval (k =<< e) = Eval (k (Eval e))++data (>>=) :: Exp a -> (a -> Exp b) -> Exp b+type instance Eval (e >>= k) = Eval (k (Eval e)) data (<=<) :: (b -> Exp c) -> (a -> Exp b) -> a -> Exp c type instance Eval ((f <=< g) x) = Eval (f (Eval (g x)))
src/Fcf/Data/Bool.hs view
@@ -78,6 +78,7 @@ data Guarded :: a -> [Guard (a -> Exp Bool) (Exp b)] -> Exp b type instance Eval (Guarded x ((p ':= y) ': ys)) = Eval (If (Eval (p x)) y (Guarded x ys))+{-# DEPRECATED Guarded "Use 'Case' instead" #-} -- | A fancy-looking pair type to use with 'Guarded'. data Guard a b = a := b
src/Fcf/Data/List.hs view
@@ -30,7 +30,6 @@ , Cons2 ) where -import GHC.TypeLits (Nat) import qualified GHC.TypeLits as TL import Fcf.Core
src/Fcf/Data/Nat.hs view
@@ -1,10 +1,15 @@ {-# LANGUAGE+ CPP, DataKinds, PolyKinds, TypeFamilies, TypeInType, TypeOperators, UndecidableInstances #-}++#if __GLASGOW_HASKELL__ >= 806+{-# LANGUAGE NoStarIsType #-}+#endif -- | Natural numbers. --
src/Fcf/Utils.hs view
@@ -6,7 +6,8 @@ RankNTypes, TypeFamilies, TypeInType,- TypeOperators #-}+ TypeOperators,+ UndecidableInstances #-} -- | Miscellaneous families. module Fcf.Utils@@ -16,8 +17,14 @@ , TyEq , Stuck , IsBool(_If)+ , Case+ , Match()+ , type (-->)+ , Is+ , Any+ , Else - -- | From "Data.Type.Bool".+ -- * From "Data.Type.Bool" , If ) where @@ -58,3 +65,59 @@ instance IsBool 'True where _If a _ = a instance IsBool 'False where _If _ b = b++-- * Case splitting++infix 0 -->++data Match j k+ = Match_ j k+ | Is_ (j -> Exp Bool) k+ | Any_ k+ | Else_ (j -> Exp k)++-- | (Limited) equivalent of @\\case { .. }@ syntax. Supports matching of exact+-- values ('-->') and final matches for any value ('Any') or for passing value+-- to subcomputation ('Else'). Examples:+--+-- @+-- type BoolToNat = Case+-- [ 'True --> 0+-- , 'False --> 1+-- ]+--+-- type NatToBool = Case+-- [ 0 --> 'False+-- , Any 'True+-- ]+--+-- type ZeroOneOrSucc = Case+-- [ 0 --> 0+-- , 1 --> 1+-- , Else ((+) 1)+-- ]+-- @+data Case :: [Match j k] -> j -> Exp k+type instance Eval (Case ms a) = Case_ ms a++type family Case_ (ms :: [Match j k]) (a :: j) :: k where+ Case_ ('Match_ a b : _ ) a = b+ Case_ ('Match_ _ _ : ms) a = Case_ ms a+ Case_ ('Is_ p b : ms) a = Case_ [ 'True --> b+ , 'False --> Case_ ms a+ ] (p @@ a)+ Case_ ('Any_ b : _ ) _ = b+ Case_ ('Else_ f : _ ) a = f @@ a++-- | Match concrete type in 'Case'.+type (-->) = ('Match_ :: j -> k -> Match j k)++-- | Match on predicate being successful with type in 'Case'.+type Is = ('Is_ :: (j -> Exp Bool) -> k -> Match j k)++-- | Match any type in 'Case'. Should be used as a final branch.+type Any = ('Any_ :: k -> Match j k)++-- | Pass type being matched in 'Case' to subcomputation. Should be used as a+-- final branch.+type Else = ('Else_ :: (j -> Exp k) -> Match j k)
test/test.hs view
@@ -8,19 +8,32 @@ import Fcf type UnitPrefix (n :: Nat) = Eval (Guarded n- '[ TyEq 0 ':= Pure ""- , TyEq 1 ':= Pure "deci"- , TyEq 2 ':= Pure "hecto"- , TyEq 3 ':= Pure "kilo"- , TyEq 6 ':= Pure "mega"- , TyEq 9 ':= Pure "giga"- , Otherwise ':= Error "Something else"- ])+ [ TyEq 0 ':= Pure ""+ , TyEq 1 ':= Pure "deci"+ , TyEq 2 ':= Pure "hecto"+ , TyEq 3 ':= Pure "kilo"+ , TyEq 6 ':= Pure "mega"+ , TyEq 9 ':= Pure "giga"+ , Otherwise ':= Error "Something else"+ ]) +type UnitPrefix' = Case+ [ 0 --> ""+ , 1 --> "deci"+ , 2 --> "hecto"+ , 3 --> "kilo"+ , 6 --> "mega"+ , 9 --> "giga"+ , Any (Error @@ "Something Else")+ ]+ -- Compile-time tests _ = Refl :: UnitPrefix 0 :~: "" _ = Refl :: UnitPrefix 9 :~: "giga"++_ = Refl :: Eval (UnitPrefix' 0) :~: ""+_ = Refl :: Eval (UnitPrefix' 3) :~: "kilo" -- Dummy