packages feed

first-class-families 0.3.0.1 → 0.4.0.0

raw patch · 5 files changed

+134/−5 lines, 5 filesdep +first-class-familiesdep ~basePVP ok

version bump matches the API change (PVP)

Dependencies added: first-class-families

Dependency ranges changed: base

API changes (from Hackage documentation)

+ Fcf: (:=) :: a -> b -> Guard a b
+ Fcf: data Guard a b
+ Fcf: data Guarded :: a -> [Guard (a -> Exp Bool) (Exp b)] -> Exp b
+ Fcf: data LiftM2 :: (a -> b -> Exp c) -> Exp a -> Exp b -> Exp c
+ Fcf: data LiftM3 :: (a -> b -> c -> Exp d) -> Exp a -> Exp b -> Exp c -> Exp d
+ Fcf: infixl 4 <*>
+ Fcf: infixr 0 $
+ Fcf: infixr 1 <=<
+ Fcf: infixr 2 ||
+ Fcf: infixr 3 &&
+ Fcf: type LiftM = (=<<)
+ Fcf: type Otherwise = ConstFn 'True
+ Fcf: type family If (b :: Bool) (x :: k) (y :: k) :: k
- Fcf: _If :: IsBool b => ((b ~ 'True) => r) -> ((b ~ 'False) => r) -> r
+ Fcf: _If :: IsBool b => (b ~ 'True => r) -> (b ~ 'False => r) -> r

Files

CHANGELOG.md view
@@ -1,14 +1,22 @@+# 0.4.0.0++- New functions (blmage)++    + `LiftM`, `LiftM2`, `LiftM3`+    + `(<=)`, `(>=)`, `(<)`, `(>)`+    + `Guarded`, `Guard((:=))`, `Otherwise`+ # 0.3.0.1  - GHC 8.6 compatibility  # 0.3.0.0 -- More new functions, thanks to isovector+- More new functions, (isovector)  # 0.2.0.0 -- A whole bunch of basic functions, thanks to isovector+- A whole bunch of basic functions (isovector) - Remove `Traverse` (now `Map`), `BimapPair`, `BimapEither` (now `Bimap`)  # 0.1.0.0
README.md view
@@ -1,8 +1,45 @@ # First-class type families [![Hackage](https://img.shields.io/hackage/v/first-class-families.svg)](https://hackage.haskell.org/package/first-class-families) [![Build Status](https://travis-ci.org/Lysxia/first-class-families.svg)](https://travis-ci.org/Lysxia/first-class-families) -[Haskell with only one type family](http://blog.poisson.chat/posts/2018-08-06-one-type-family.html) (blogpost)+For example, consider this simple type family: -See `src/Fcf`.+```haskell+type family   FromMaybe (a :: k) (m :: Maybe k) :: k+type instance FromMaybe a 'Nothing  = a+type instance FromMaybe a ('Just b) = b+```++With first-class-families, it translates to a `data` declaration+and instances for a single `Eval` family:++```haskell+import Fcf++data FromMaybe :: k -> Maybe k -> Exp k+type instance Eval (FromMaybe a 'Nothing)  = a+type instance Eval (FromMaybe a ('Just b)) = b+```++That way, the `FromMaybe` constructor can be passed to higher-order fcfs.++```haskell+Eval (Map (FromMaybe 0) '[ 'Just 1, 'Nothing ])  =  '[ 1, 0 ] :: [Nat]+```++Essential language extensions:++```haskell+{-# LANGUAGE+    DataKinds,+    PolyKinds,+    TypeFamilies,+    TypeInType,+    TypeOperators,+    UndecidableInstances #-}+```++## See also++[Haskell with only one type family](http://blog.poisson.chat/posts/2018-08-06-one-type-family.html) (blogpost)  --- 
first-class-families.cabal view
@@ -1,5 +1,5 @@ name:                first-class-families-version:             0.3.0.1+version:             0.4.0.0 synopsis:   First class type families description:@@ -28,6 +28,15 @@     base >= 4.9 && < 5   ghc-options:         -Wall   default-language:    Haskell2010++test-suite fcf-test+  type:                exitcode-stdio-1.0+  hs-source-dirs:      test+  main-is:             test.hs+  default-language:    Haskell2010+  build-depends:+    base,+    first-class-families  source-repository head   type:     git
src/Fcf.hs view
@@ -76,6 +76,14 @@ data (<=<) :: (b -> Exp c) -> (a -> Exp b) -> a -> Exp c type instance Eval ((f <=< g) x) = Eval (f (Eval (g x))) +type LiftM = (=<<)++data LiftM2 :: (a -> b -> Exp c) -> Exp a -> Exp b -> Exp c+type instance Eval (LiftM2 f x y) = Eval (f (Eval x) (Eval y))++data LiftM3 :: (a -> b -> c -> Exp d) -> Exp a -> Exp b -> Exp c -> Exp d+type instance Eval (LiftM3 f x y z) = Eval (f (Eval x) (Eval y) (Eval z))+ data Join :: Exp (Exp a) -> Exp a type instance Eval (Join e) = Eval (Eval e) @@ -294,6 +302,33 @@ type instance Eval (Not 'True)  = 'False type instance Eval (Not 'False) = 'True +-- | A conditional choosing the first branch whose guard @a -> 'Exp' 'Bool'@+-- accepts a given value @a@.+--+-- === Example+--+-- @+-- type UnitPrefix n = '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"+--    ])+-- @+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))++-- | A fancy-looking pair type to use with 'Guarded'.+data Guard a b = a := b+infixr 0 :=++-- | A catch-all guard for 'Guarded'.+type Otherwise = ConstFn 'True+ -- ** Nat  data (+) :: Nat -> Nat -> Exp Nat@@ -307,6 +342,18 @@  data (^) :: Nat -> Nat -> Exp Nat type instance Eval ((^) a b) = a TL.^ b++data (<=) :: Nat -> Nat -> Exp Bool+type instance Eval ((<=) a b) = a TL.<=? b++data (>=) :: Nat -> Nat -> Exp Bool+type instance Eval ((>=) a b) = b TL.<=? a++data (<) :: Nat -> Nat -> Exp Bool+type instance Eval ((<) a b) = Eval (Not =<< (a >= b))++data (>) :: Nat -> Nat -> Exp Bool+type instance Eval ((>) a b) = Eval (Not =<< (a <= b))  -- ** Other 
+ test/test.hs view
@@ -0,0 +1,28 @@+{-# LANGUAGE+    DataKinds,+    KindSignatures,+    TypeOperators #-}++import Data.Type.Equality ((:~:)(Refl))+import GHC.TypeLits (Nat)+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"+   ])++-- Compile-time tests++_ = Refl :: UnitPrefix 0 :~: ""+_ = Refl :: UnitPrefix 9 :~: "giga"++-- Dummy++main :: IO ()+main = pure ()