Safe Haskell | None |
---|
The HList library
This module re-exports everything needed to use HList.
- module Data.HList.FakePrelude
- module Data.HList.HListPrelude
- module Data.HList.HArray
- module Data.HList.HOccurs
- module Data.HList.HTypeIndexed
- module Data.HList.Record
- module Data.HList.HList
- module Data.HList.TypeEqO
- module Data.HList.TIP
- module Data.HList.TIC
- module Data.HList.HZip
- module Data.HList.Variant
- class Kw fn arg_def r where
- recToKW :: forall a b. (HMapAux TaggedToKW a b, SameLength a b, SameLength b a, HConcat b) => Record a -> HList (HConcatR b)
- class IsKeyFN t flag | t -> flag
- data K s c
- data ErrReqdArgNotFound x
- data ErrUnexpectedKW x
- module Data.HList.Labelable
- module Data.HList.Label3
- module Data.HList.MakeLabels
- module Data.HList.RecordPuns
Documentation
module Data.HList.FakePrelude
module Data.HList.HListPrelude
module Data.HList.HArray
module Data.HList.HOccurs
module Data.HList.HTypeIndexed
module Data.HList.Record
module Data.HList.HList
module Data.HList.TypeEqO
module Data.HList.TIP
module Data.HList.TIC
module Data.HList.HZip
module Data.HList.Variant
Data.HList.Keyword
the "public" parts. More examples are in the module documentation.
class Kw fn arg_def r whereSource
kw
takes a HList
whose first element is a function, and the rest
of the elements are default values.
A useful trick is to have a final argument ()
which is not
eaten up by a label (A only takes 1 argument). That way when you supply
the () it knows there are no more arguments (?).
>>>
data A = A
>>>
instance IsKeyFN (A -> a -> b) True
>>>
let f A a () = a + 1
>>>
let f' = f .*. A .*. 1 .*. HNil
>>>
kw f' A 0 ()
1
>>>
kw f' ()
2
recToKW :: forall a b. (HMapAux TaggedToKW a b, SameLength a b, SameLength b a, HConcat b) => Record a -> HList (HConcatR b)Source
convert a Record
into a list that can supply
default arguments for kw
A bit of setup:
>>>
:set -XQuasiQuotes
>>>
import Data.HList.RecordPuns
>>>
let f (_ :: Label "a") a (_ :: Label "b") b () = a `div` b
>>>
let a = 2; b = 1; f' = f .*. recToKW [pun| a b |]
>>>
kw f' ()
2
>>>
kw f' (Label :: Label "a") 10 ()
10
class IsKeyFN t flag | t -> flagSource
All our keywords must be registered
~ Bool False flag => IsKeyFN k t flag | overlapping/fallback case |
IsKeyFN * (Label Symbol s -> a -> b) True | labels that impose no restriction on the type of the (single) argument which follows
|
~ * r (c -> b) => IsKeyFN * (K k s c -> r) True | The purpose of this instance is to be able to use the same Symbol
(type-level string) at different types. If they are supposed to be the same,
then use
therefore the following options works:
But you cannot leave off all |
~ * r (c -> b) => IsKeyFN * (K k s c -> r) True | The purpose of this instance is to be able to use the same Symbol
(type-level string) at different types. If they are supposed to be the same,
then use
therefore the following options works:
But you cannot leave off all |
data ErrReqdArgNotFound x Source
data ErrUnexpectedKW x Source
Labels
there are really only two options for now, but there are a couple different styles for the first option here:
GHC supports type-level strings (Symbol
), and these can be
labels. You can refer to these strings using an unwieldy syntax. For
example if you want to store a value 5
in a record rec
with a field
called "x"
, and then get it out again:
let rec = (Label
:: Label "x") .=.
5 .*.
emptyRecord
rec .!.
(Label :: Label "x")
To avoid that pain, you can have a definition x = Label :: Label x
.
and just use x
instead of repeating Label :: Label "x"
so that
a lookup becomes:
rec .!. x
See makeLabels6
for automating the x = Label :: Label "x"
.
Instances from Data.HList.Label6
>>>
:set -XDataKinds
>>>
(Label :: Label "x") .=. (5::Int) .*. emptyRecord
Record{x=5}
>>>
let x = Label :: Label "x"
>>>
let r = x .=. (5::Int) .*. emptyRecord
>>>
r .!. x
5
module Data.HList.Labelable
Rather than having the x = Label :: Label "x"
, the labels
generated by makeLabelable
also double lenses for Control.Lens.
Here is an example of how much better that is:
>>>
:set -XNoMonomorphismRestriction -XDataKinds -XPolyKinds
>>>
import Control.Lens
>>>
let x = hLens' (Label :: Label "x")
The Label6 method:
>>>
let r = (Label :: Label "x") .=. "5" .*. emptyRecord
The Labelable way:
>>>
let r2 = x .==. "5" .*. emptyRecord
>>>
r ^. x
"5"
>>>
r2 ^. x
"5"
>>>
r & x .~ ()
Record{x=()}
namespaced labels
module Data.HList.Label3
template haskell for automating different types of labels
module Data.HList.MakeLabels
quasiquoter pun
helps to avoid needing a proxy value with
type Label
in the first place: when you take values out of or into
records with pattern matching, the variable name determines the label
name.
module Data.HList.RecordPuns
Data.HList.Data
This modules provide useful instances. A useful application can be
found in examples/cmdargs.hs