3One of the most useful types I've come across in Haskell is the type of
4"heterogeneous lists". This is the same as the [Rec](http://hackage.haskell.org/package/vinyl-0.8.1.1/docs/Data-Vinyl-Core.html)
5datatype from the [vinyl](http://hackage.haskell.org/package/vinyl) library.
6It's also the same as the [NP](http://hackage.haskell.org/package/generics-sop-0.3.2.0/docs/Generics-SOP-NP.html)
7datatype from the [generics-sop](http://hackage.haskell.org/package/generics-sop) library.
8Squeal makes heavy use of this type.
11>>> import Generics.SOP (NP(..))
13type role NP representational nominal
14data NP (a :: k -> *) (b :: [k]) where
15 Nil :: forall k (a :: k -> *). NP a '[]
16 (:*) :: forall k (a :: k -> *) (x :: k) (xs :: [k]).
17 (a x) -> (NP a xs) -> NP a (x : xs)
18 -- Defined in ‘Generics.SOP.NP’
21This type allows us to construct "product" types, where the types of the individual
22"terms" are hosted at the type level.
26>>> import Generics.SOP (I(..))
27>>> let example = I "foo" :* I pi :* Nil :: NP I '[String, Double]
29I "foo" :* I 3.141592653589793 :* Nil
32One thing Squeal uses `NP` for is to form lists of aliases,
33using GHC's `OverloadedLabels` extension, hosting the names
34of the aliases themselves at the type level.
37>>> :set -XKindSignatures -XOverloadedLabels -XFlexibleInstances -XMultiParamTypeClasses
38>>> import GHC.TypeLits
39>>> import GHC.OverloadedLabels
40>>> data Alias (alias :: Symbol) = Alias deriving (Eq,Ord,Show)
41>>> instance IsLabel label (Alias label) where fromLabel = Alias
42>>> let aliases = #foo :* #bar :* Nil :: NP Alias '["foo", "bar"]
45However, it's very ugly to have to end every list with `:* Nil`.
46When I announced the release of Squeal, people rightly [complained](https://www.reddit.com/r/haskell/comments/6yr5v6/announcing_squeal_a_deep_embedding_of_sql_in/dmq8vvn)
47about the syntactic noise. Luckily, there's a neat trick we can use to get rid of it.
48Making an `IsLabel` instance not only for elements of our list
49but also for lists of length 1, we can ask GHC to interpret
50the last label as a list.
53>>> instance IsLabel label (NP Alias '[label]) where fromLabel = Alias :* Nil
54>>> let aliases' = #foo :* #bar :: NP Alias '["foo", "bar"]
57Version 0.3.1 of Squeal enables the "Scrap your Nils" trick for
58heterogeneous lists of `Alias`es, `Aliased` expressions, `PGlabel`s and `By`s
59with the typeclasses `IsLabel`, `IsQualified`, `IsPGlabel`,
60and the new `Aliasable` typeclass, to eliminate all need of using `Nil` in a list.
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list