type-level-kv-list 0.2.0.0 → 1.0.0
raw patch · 7 files changed
+185/−324 lines, 7 filesdep ~basePVP ok
version bump matches the API change (PVP)
Dependency ranges changed: base
API changes (from Hackage documentation)
- Data.KVList: (&.) :: (KnownSymbol key, HasKey key kvs v) => KVList kvs -> ListKey key -> v
- Data.KVList: (&=) :: (KnownSymbol k, Appended kvs '[k := v] ~ appended) => KVList kvs -> (k := v) -> KVList appended
- Data.KVList: ListKey :: ListKey (t :: Symbol)
- Data.KVList: [:=] :: ListKey a -> b -> a := b
- Data.KVList: data (key :: Symbol) := (value :: Type)
- Data.KVList: data KVList (kvs :: [Type])
- Data.KVList: data ListKey (t :: Symbol)
- Data.KVList: empty :: KVList '[]
- Data.KVList: get :: (KnownSymbol key, HasKey key kvs v) => ListKey key -> KVList kvs -> v
- Data.KVList: infix 2 :=
- Data.KVList: infixl 1 &=
- Data.KVList: infixl 9 &.
- Data.KVList: instance (l GHC.Types.~ l') => GHC.OverloadedLabels.IsLabel l (Data.KVList.ListKey l')
- Data.KVList: instance GHC.Classes.Eq (Data.KVList.ListKey t)
- Data.KVList: instance GHC.Show.Show (Data.KVList.ListKey t)
- Data.KVList: instance GHC.Show.Show value => GHC.Show.Show (key Data.KVList.:= value)
- Data.KVList: kvcons :: KnownSymbol k => (k := v) -> KVList kvs -> KVList ((k := v) : kvs)
- Data.KVList: singleton :: KnownSymbol k => (k := v) -> KVList '[k := v]
- Data.KVList: type HasKey (key :: Symbol) (kvs :: [Type]) (v :: Type) = HasKey_ key kvs kvs v
+ Data.TypeLevelKVList: (:.) :: a -> b -> (:.) a b
+ Data.TypeLevelKVList: Null :: Null
+ Data.TypeLevelKVList: data (:.) a b
+ Data.TypeLevelKVList: data Null
+ Data.TypeLevelKVList: get :: (HasKey list pkey (Lookup pkey list)) => pkey -> list -> Lookup pkey list
+ Data.TypeLevelKVList: instance (Data.TypeLevelKVList.NamedList b, GHC.TypeLits.KnownSymbol k) => Data.TypeLevelKVList.NamedList (Data.TypeLevelKVList.NamedVal v k Data.TypeLevelKVList.:. b)
+ Data.TypeLevelKVList: instance (GHC.Classes.Eq b, GHC.Classes.Eq a) => GHC.Classes.Eq (a Data.TypeLevelKVList.:. b)
+ Data.TypeLevelKVList: instance (GHC.Show.Show b, GHC.Show.Show a) => GHC.Show.Show (a Data.TypeLevelKVList.:. b)
+ Data.TypeLevelKVList: instance Data.TypeLevelKVList.NamedList Data.TypeLevelKVList.Null
+ Data.TypeLevelKVList: instance GHC.Classes.Eq Data.TypeLevelKVList.Null
+ Data.TypeLevelKVList: instance GHC.Show.Show Data.TypeLevelKVList.Null
+ Data.TypeLevelKVList: instance forall k (k1 :: k). Data.TypeLevelKVList.HasKey Data.TypeLevelKVList.Null (Data.Proxy.Proxy k1) Data.TypeLevelKVList.Null
+ Data.TypeLevelKVList: instance forall k b (k1 :: k) v a. Data.TypeLevelKVList.HasKey b (Data.Proxy.Proxy k1) v => Data.TypeLevelKVList.HasKey (a Data.TypeLevelKVList.:. b) (Data.Proxy.Proxy k1) v
+ Data.TypeLevelKVList: instance forall k v (k1 :: k) b. Data.TypeLevelKVList.HasKey (Data.TypeLevelKVList.NamedVal v k1 Data.TypeLevelKVList.:. b) (Data.Proxy.Proxy k1) v
+ Data.TypeLevelKVList: keys :: NamedList layout => Proxy layout -> [String]
+ Data.TypeLevelKVList: keys' :: NamedList k => k -> [String]
+ Data.TypeLevelKVList: namedVal :: v -> NamedVal v k
+ Data.TypeLevelKVList: type NamedVal v key = (Proxy key, v)
Files
- README.md +0/−9
- src/Data/KVList.hs +0/−133
- src/Data/TypeLevelKVList.hs +127/−0
- test/DocTest.hs +0/−57
- test/Doctest.hs +17/−0
- test/Spec.hs +2/−0
- type-level-kv-list.cabal +39/−125
− README.md
@@ -1,9 +0,0 @@-[](https://github.com/arowM/type-level-kv-list/actions/workflows/test.yaml)-[](https://hackage.haskell.org/package/type-level-kv-list)-[](http://stackage.org/lts/package/type-level-kv-list)-[](http://stackage.org/nightly/package/type-level-kv-list)--# type-level-kv-list--This library provides a brief implementation for extensible records.-It is sensitive to the ordering of key-value items, but has simple type constraints and provides short compile time.
− src/Data/KVList.hs
@@ -1,133 +0,0 @@-{-| This library provide a brief implementation for extensible records.- It is sensitive to the ordering of key-value items, but has simple type constraints and provides short compile time.--}--{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE CPP #-}-{-# LANGUAGE UndecidableInstances #-}--module Data.KVList- (- -- * Constructors- -- $setup- KVList- , (:=)((:=))- , (&=)- , kvcons- , empty- , singleton- , ListKey(..)-- -- * Operators- , get- , HasKey- , (&.)- )-where--import Prelude--import Data.Kind (Constraint, Type)-import Data.Typeable (Typeable, typeOf)-import GHC.TypeLits (KnownSymbol, Symbol, TypeError, ErrorMessage(Text))-import GHC.OverloadedLabels (IsLabel(..))-import Unsafe.Coerce (unsafeCoerce)----- Constructors--{- $setup #constructors#- We can create type level KV list as follows.-- >>> :set -XOverloadedLabels -XTypeOperators- >>> import Prelude- >>> import Data.KVList (empty, KVList, (:=)((:=)), (&.), (&=))- >>> let sampleList = empty &= #foo := "str" &= #bar := 34- >>> type SampleList = KVList '[ "foo" := String, "bar" := Int ]--}--{-| A value with type level key.--}-data KVList (kvs :: [Type]) where- KVNil :: KVList '[]- KVCons :: (KnownSymbol key) => key := v -> KVList xs -> KVList ((key := v) ': xs)--{-| -}-empty :: KVList '[]-empty = KVNil--(&=) :: (KnownSymbol k, Appended kvs '[k := v] ~ appended) => KVList kvs -> (k := v) -> KVList appended-(&=) kvs kv = append kvs (singleton kv)-{-# INLINE (&=) #-}--infixl 1 &=--{-| -}-kvcons :: (KnownSymbol k) => (k := v) -> KVList kvs -> KVList ((k := v) ': kvs)-kvcons = KVCons--{-| -}-data (key :: Symbol) := (value :: Type) where- (:=) :: ListKey a -> b -> a := b-infix 2 :=--deriving instance (Show value) => Show (key := value)--{-| -}-type HasKey (key :: Symbol) (kvs :: [Type]) (v :: Type) = HasKey_ key kvs kvs v--type family HasKey_ (key :: Symbol) (kvs :: [Type]) (orig :: [Type]) (v :: Type) :: Constraint where- HasKey_ key '[] '[] v = TypeError ('Text "The KVList is empty.")- HasKey_ key '[] orig v = TypeError ('Text "The Key is not in the KVList.")- HasKey_ key ((key := val) ': _) _ v = (val ~ v)- HasKey_ key (_ ': kvs) orig v = HasKey_ key kvs orig v--{-| -}-type family Appended kvs1 kv2 :: [Type] where- Appended '[] kv2 = kv2- Appended (kv ': kvs) kv2 =- kv ': Appended kvs kv2--{-| -}-append :: (Appended kvs1 kvs2 ~ appended) => KVList kvs1 -> KVList kvs2 -> KVList appended-append KVNil kvs2 = kvs2-append (KVCons kv kvs) kvs2 = KVCons kv (append kvs kvs2)---{-| -}-singleton :: (KnownSymbol k) => (k := v) -> KVList '[ k := v ]-singleton kv = KVCons kv KVNil---{-| -}-get :: (KnownSymbol key, HasKey key kvs v) => ListKey key -> KVList kvs -> v-get p kvs = get_ p kvs kvs--get_ :: (KnownSymbol key, HasKey key orig v) => ListKey key -> KVList kvs -> KVList orig -> v-get_ _ KVNil KVNil = error "Unreachable: The KVList is empty."-get_ _ KVNil _ = error "Unreachable: The Key is not in the KVList."-get_ p (KVCons (k := v) kvs) orig =- if typeOf p == typeOf k then- unsafeCoerce v- else- get_ p kvs orig---{-| -}-(&.) :: (KnownSymbol key, HasKey key kvs v) => KVList kvs -> ListKey key -> v-(&.) kvs k = get k kvs-infixl 9 &.--{-| 'ListKey' is just a proxy, but needed to implement a non-orphan 'IsLabel' instance.-In most cases, you only need to create a `ListKey` instance with @OverloadedLabels@, such as `#foo`.--}-data ListKey (t :: Symbol)- = ListKey- deriving (Show, Eq, Typeable)--instance l ~ l' => IsLabel (l :: Symbol) (ListKey l') where-#if MIN_VERSION_base(4, 10, 0)- fromLabel = ListKey-#else- fromLabel _ = ListKey-#endif
+ src/Data/TypeLevelKVList.hs view
@@ -0,0 +1,127 @@+{-|+ This module supply a way to construct type safe key-value pair list+ and convenient operations for the type.+-}++{-# LANGUAGE DataKinds #-}+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeInType #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE MultiParamTypeClasses #-}+{-# LANGUAGE IncoherentInstances #-}++module Data.TypeLevelKVList+ (+ -- * Constructors+ -- $setup+ NamedVal+ , namedVal+ , (:.)(..)+ , Null(..)++ -- * Operators+ , get+ , Lookup+ , keys+ , keys'+ )+where++import Data.Proxy (Proxy(..))+import Data.Typeable (Typeable)+import GHC.TypeLits (KnownSymbol, symbolVal)++-- Constructors++{- $setup #constructors#+ We can create type level KV list as follows.++ >>> :set -XDataKinds -XTypeOperators+ >>> let sampleList = (namedVal "str" :: NamedVal String "foo") :. (namedVal 34 :: NamedVal Int "bar") :. Null+ >>> type SampleList = NamedVal String "foo" :. NamedVal Int "bar" :. Null+-}++{-| A value with type level key.+ -}+type NamedVal v key = (Proxy key, v)++{-| A convenient function to construct type level KV list.+ -}+namedVal :: v -> NamedVal v k+namedVal a = (Proxy, a)++{-| Type level list cons.+ -}+data a :. b = a :. b+ deriving (Typeable, Eq, Show)+infixr 8 :.++{-| Type level empty list.+ -}+data Null = Null+ deriving (Typeable, Eq, Show)++{-| Type level @lookup :: k -> [(k, a)] -> a@.+ -}+type family Lookup pkey list where+ Lookup pk ((pk, v) :. b) = v+ Lookup pk ((px, v) :. b) = Lookup pk b+ Lookup pk Null = Null++{-| Main class for a list of values with type level key+ -}+class NamedList layout where+ type family NamedList' layout+ {-|+ >>> keys (Proxy :: Proxy SampleList)+ ["foo","bar"]+ -}+ keys :: Proxy layout -> [String]++instance (NamedList b, KnownSymbol k) => NamedList (NamedVal v k :. b) where+ type NamedList' (NamedVal v k :. b) = NamedVal v k :. NamedList' b+ keys _ = symbolVal (Proxy :: Proxy k) : keys (Proxy :: Proxy b)++instance NamedList Null where+ type NamedList' Null = Null+ keys _ = []++{-| Chek if the key is included in type level list.+ -}+class HasKey list pkey value where+ get' :: pkey -> list -> value++instance HasKey (NamedVal v k :. b) (Proxy k) v where+ get' _ ((_, a) :. _) = a++instance HasKey b (Proxy k) v =>+ HasKey (a :. b) (Proxy k) v where+ get' p (_ :. b) = get' p b++instance HasKey Null (Proxy k) Null where+ get' _ Null = Null++{-|+ >>> get (Proxy :: Proxy "foo") sampleList+ "str"++ >>> get (Proxy :: Proxy "bar") sampleList+ 34++ >>> get (Proxy :: Proxy "baz") sampleList+ Null+-}+get :: (HasKey list pkey (Lookup pkey list))+ => pkey -> list -> Lookup pkey list+get (pkey :: pkey) (list :: list) =+ get' pkey list :: Lookup pkey list++{-|+ >>> keys' sampleList+ ["foo","bar"]+-}+keys' :: NamedList k => k -> [String]+keys' (_ :: k) = keys (Proxy :: Proxy k)
− test/DocTest.hs
@@ -1,57 +0,0 @@-module Main (main) where--import Prelude--import System.FilePath.Glob (glob)-import Test.DocTest (doctest)--main :: IO ()-main = glob "src/**/*.hs" >>= doDocTest--doDocTest :: [String] -> IO ()-doDocTest options =- doctest $- options <>- ghcExtensions--ghcExtensions :: [String]-ghcExtensions =- [ "-XBangPatterns"- , "-XBinaryLiterals"- , "-XConstraintKinds"- , "-XDataKinds"- , "-XDefaultSignatures"- , "-XDeriveDataTypeable"- , "-XDeriveFoldable"- , "-XDeriveFunctor"- , "-XDeriveGeneric"- , "-XDeriveTraversable"- , "-XDoAndIfThenElse"- , "-XDuplicateRecordFields"- , "-XEmptyDataDecls"- , "-XExistentialQuantification"- , "-XFlexibleContexts"- , "-XFlexibleInstances"- , "-XFunctionalDependencies"- , "-XGADTs"- , "-XGeneralizedNewtypeDeriving"- , "-XInstanceSigs"- , "-XKindSignatures"- , "-XLambdaCase"- , "-XMultiParamTypeClasses"- , "-XMultiWayIf"- , "-XNamedFieldPuns"- , "-XNoImplicitPrelude"- , "-XOverloadedStrings"- , "-XPartialTypeSignatures"- , "-XPatternGuards"- , "-XPolyKinds"- , "-XRankNTypes"- , "-XRecordWildCards"- , "-XScopedTypeVariables"- , "-XStandaloneDeriving"- , "-XTupleSections"- , "-XTypeFamilies"- , "-XTypeSynonymInstances"- , "-XViewPatterns"- ]
+ test/Doctest.hs view
@@ -0,0 +1,17 @@+module Main where++import Data.Monoid ((<>))+import System.FilePath.Glob (glob)+import Test.DocTest (doctest)++main :: IO ()+main = glob "src/**/*.hs" >>= doDocTest++doDocTest :: [String] -> IO ()+doDocTest options = doctest $ options <> ghcExtensions++ghcExtensions :: [String]+ghcExtensions =+ [ "-XDataKinds"+ , "-XTypeOperators"+ ]
+ test/Spec.hs view
@@ -0,0 +1,2 @@+main :: IO ()+main = putStrLn "Test suite not yet implemented"
type-level-kv-list.cabal view
@@ -1,130 +1,44 @@-cabal-version: 1.12+name: type-level-kv-list+version: 1.0.0+synopsis: A module for hash map like object with type level keys.+description: Please see README.md+homepage: https://github.com/arowM/type-level-kv-list#readme+license: MIT+license-file: LICENSE+author: Kadzuya Okamoto+maintainer: arow.okamoto+github@gmail.com+copyright: 2016 Kadzuya Okamoto+category: Data+build-type: Simple+-- extra-source-files:+cabal-version: >=1.10 --- This file has been generated from package.yaml by hpack version 0.34.4.------ see: https://github.com/sol/hpack+library+ hs-source-dirs: src+ exposed-modules: Data.TypeLevelKVList+ build-depends: base >= 4.7 && < 5+ default-language: Haskell2010 -name: type-level-kv-list-version: 0.2.0.0-synopsis: Type level Key-Value list.-description: This library provides a brief implementation for extensible records.-category: Data-homepage: https://github.com/arowM/type-level-kv-list#readme-bug-reports: https://github.com/arowM/type-level-kv-list/issues-author: Sakura-chan the Goat-maintainer: arow.okamoto+github@gmail.com-copyright: 2016 Sakura-chan the Goat-license: MIT-license-file: LICENSE-build-type: Simple-extra-source-files:- README.md+test-suite type-level-kv-list-test+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Spec.hs+ build-depends: base+ , type-level-kv-list+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010 +test-suite doctest+ type: exitcode-stdio-1.0+ hs-source-dirs: test+ main-is: Doctest.hs+ build-depends: base+ , Glob+ , doctest+ , type-level-kv-list+ ghc-options: -threaded -rtsopts -with-rtsopts=-N+ default-language: Haskell2010+ source-repository head- type: git+ type: git location: https://github.com/arowM/type-level-kv-list--library- exposed-modules:- Data.KVList- other-modules:- Paths_type_level_kv_list- hs-source-dirs:- src- default-extensions:- BangPatterns- BinaryLiterals- ConstraintKinds- DataKinds- DefaultSignatures- DeriveDataTypeable- DeriveFoldable- DeriveFunctor- DeriveGeneric- DeriveTraversable- DoAndIfThenElse- DuplicateRecordFields- EmptyDataDecls- ExistentialQuantification- FlexibleContexts- FlexibleInstances- FunctionalDependencies- GADTs- GeneralizedNewtypeDeriving- InstanceSigs- KindSignatures- LambdaCase- MultiParamTypeClasses- MultiWayIf- NamedFieldPuns- OverloadedStrings- PartialTypeSignatures- PatternGuards- PolyKinds- RankNTypes- RecordWildCards- ScopedTypeVariables- StandaloneDeriving- Strict- StrictData- TupleSections- TypeFamilies- TypeSynonymInstances- ViewPatterns- ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints- build-depends:- base >=4.7 && <5- default-language: Haskell2010--test-suite doctest- type: exitcode-stdio-1.0- main-is: DocTest.hs- hs-source-dirs:- test- default-extensions:- BangPatterns- BinaryLiterals- ConstraintKinds- DataKinds- DefaultSignatures- DeriveDataTypeable- DeriveFoldable- DeriveFunctor- DeriveGeneric- DeriveTraversable- DoAndIfThenElse- DuplicateRecordFields- EmptyDataDecls- ExistentialQuantification- FlexibleContexts- FlexibleInstances- FunctionalDependencies- GADTs- GeneralizedNewtypeDeriving- InstanceSigs- KindSignatures- LambdaCase- MultiParamTypeClasses- MultiWayIf- NamedFieldPuns- OverloadedStrings- PartialTypeSignatures- PatternGuards- PolyKinds- RankNTypes- RecordWildCards- ScopedTypeVariables- StandaloneDeriving- Strict- StrictData- TupleSections- TypeFamilies- TypeSynonymInstances- ViewPatterns- ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints- build-depends:- Glob- , base >=4.7 && <5- , doctest- , type-level-kv-list- default-language: Haskell2010