squeal-postgresql-0.9.0.0: Squeal PostgreSQL Library
Copyright(c) Eitan Chatav 2019
Maintainereitan@morphism.tech
Stabilityexperimental
Safe HaskellNone
LanguageHaskell2010

Squeal.PostgreSQL.Type.List

Description

Haskell singly-linked lists are very powerful. This module provides functionality for type-level lists, heterogeneous lists and type aligned lists.

Synopsis

Heterogeneous List

data NP (a :: k -> Type) (b :: [k]) where #

An n-ary product.

The product is parameterized by a type constructor f and indexed by a type-level list xs. The length of the list determines the number of elements in the product, and if the i-th element of the list is of type x, then the i-th element of the product is of type f x.

The constructor names are chosen to resemble the names of the list constructors.

Two common instantiations of f are the identity functor I and the constant functor K. For I, the product becomes a heterogeneous list, where the type-level list describes the types of its components. For K a, the product becomes a homogeneous list, where the contents of the type-level list are ignored, but its length still specifies the number of elements.

In the context of the SOP approach to generic programming, an n-ary product describes the structure of the arguments of a single data constructor.

Examples:

I 'x'    :* I True  :* Nil  ::  NP I       '[ Char, Bool ]
K 0      :* K 1     :* Nil  ::  NP (K Int) '[ Char, Bool ]
Just 'x' :* Nothing :* Nil  ::  NP Maybe   '[ Char, Bool ]

Constructors

Nil :: forall k (a :: k -> Type). NP a ('[] :: [k]) 
(:*) :: forall k (a :: k -> Type) (x :: k) (xs :: [k]). a x -> NP a xs -> NP a (x ': xs) infixr 5 

Instances

Instances details
(Has tab (Join from lat) row, Has col row ty, GroupedBy tab col bys, columns ~ '[col ::: ty]) => IsQualified tab col (NP (Aliased (Expression ('Grouped bys) lat with db params from)) columns) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

(!) :: Alias tab -> Alias col -> NP (Aliased (Expression ('Grouped bys) lat with db params from)) columns Source #

(Has tab (Join from lat) row, Has col row ty, GroupedBy tab col bys, tys ~ '[ty]) => IsQualified tab col (NP (Expression ('Grouped bys) lat with db params from) tys) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

(!) :: Alias tab -> Alias col -> NP (Expression ('Grouped bys) lat with db params from) tys Source #

(Has tab (Join from lat) row, Has col row ty, columns ~ '[col ::: ty]) => IsQualified tab col (NP (Aliased (Expression 'Ungrouped lat with db params from)) columns) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

(!) :: Alias tab -> Alias col -> NP (Aliased (Expression 'Ungrouped lat with db params from)) columns Source #

(Has tab (Join from lat) row, Has col row ty, tys ~ '[ty]) => IsQualified tab col (NP (Expression 'Ungrouped lat with db params from) tys) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

(!) :: Alias tab -> Alias col -> NP (Expression 'Ungrouped lat with db params from) tys Source #

(Has rel rels cols, Has col cols ty, bys ~ '['(rel, col)]) => IsQualified rel col (NP (By rels) bys) Source # 
Instance details

Defined in Squeal.PostgreSQL.Query.Table

Methods

(!) :: Alias rel -> Alias col -> NP (By rels) bys Source #

HTrans (NP :: (k1 -> Type) -> [k1] -> Type) (NP :: (k2 -> Type) -> [k2] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

htrans :: forall c (xs :: l1) (ys :: l2) proxy f g. AllZipN (Prod NP) c xs ys => proxy c -> (forall (x :: k10) (y :: k20). c x y => f x -> g y) -> NP f xs -> NP g ys #

hcoerce :: forall (f :: k10 -> Type) (g :: k20 -> Type) (xs :: l1) (ys :: l2). AllZipN (Prod NP) (LiftedCoercible f g) xs ys => NP f xs -> NP g ys #

HSequence (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

hsequence' :: forall (xs :: l) f (g :: k0 -> Type). (SListIN NP xs, Applicative f) => NP (f :.: g) xs -> f (NP g xs) #

hctraverse' :: forall c (xs :: l) g proxy f f'. (AllN NP c xs, Applicative g) => proxy c -> (forall (a :: k0). c a => f a -> g (f' a)) -> NP f xs -> g (NP f' xs) #

htraverse' :: forall (xs :: l) g f f'. (SListIN NP xs, Applicative g) => (forall (a :: k0). f a -> g (f' a)) -> NP f xs -> g (NP f' xs) #

HTraverse_ (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

hctraverse_ :: forall c (xs :: l) g proxy f. (AllN NP c xs, Applicative g) => proxy c -> (forall (a :: k0). c a => f a -> g ()) -> NP f xs -> g () #

htraverse_ :: forall (xs :: l) g f. (SListIN NP xs, Applicative g) => (forall (a :: k0). f a -> g ()) -> NP f xs -> g () #

HCollapse (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

hcollapse :: forall (xs :: l) a. SListIN NP xs => NP (K a) xs -> CollapseTo NP a #

HAp (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

hap :: forall (f :: k0 -> Type) (g :: k0 -> Type) (xs :: l). Prod NP (f -.-> g) xs -> NP f xs -> NP g xs #

HPure (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

Methods

hpure :: forall (xs :: l) f. SListIN NP xs => (forall (a :: k0). f a) -> NP f xs #

hcpure :: forall c (xs :: l) proxy f. AllN NP c xs => proxy c -> (forall (a :: k0). c a => f a) -> NP f xs #

(KnownSymbol alias, tys ~ '[alias ::: ty]) => Aliasable alias (expression ty) (NP (Aliased expression) tys) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.Alias

Methods

as :: expression ty -> Alias alias -> NP (Aliased expression) tys Source #

Additional (NP expr :: [a] -> Type) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.List

Methods

also :: forall (ys :: [a0]) (xs :: [a0]). NP expr ys -> NP expr xs -> NP expr (Join xs ys) Source #

IsPGlabel label (y -> NP (K y :: Symbol -> Type) '[label]) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.Schema

Methods

label :: y -> NP (K y) '[label] Source #

aliases ~ '[alias] => IsLabel alias (NP Alias aliases) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.Alias

Methods

fromLabel :: NP Alias aliases #

(HasUnique tab (Join from lat) row, Has col row ty, GroupedBy tab col bys, columns ~ '[col ::: ty]) => IsLabel col (NP (Aliased (Expression ('Grouped bys) lat with db params from)) columns) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

fromLabel :: NP (Aliased (Expression ('Grouped bys) lat with db params from)) columns #

(HasUnique tab (Join from lat) row, Has col row ty, GroupedBy tab col bys, tys ~ '[ty]) => IsLabel col (NP (Expression ('Grouped bys) lat with db params from) tys) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

fromLabel :: NP (Expression ('Grouped bys) lat with db params from) tys #

(HasUnique tab (Join from lat) row, Has col row ty, columns ~ '[col ::: ty]) => IsLabel col (NP (Aliased (Expression 'Ungrouped lat with db params from)) columns) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

fromLabel :: NP (Aliased (Expression 'Ungrouped lat with db params from)) columns #

(HasUnique tab (Join from lat) row, Has col row ty, tys ~ '[ty]) => IsLabel col (NP (Expression 'Ungrouped lat with db params from) tys) Source # 
Instance details

Defined in Squeal.PostgreSQL.Expression

Methods

fromLabel :: NP (Expression 'Ungrouped lat with db params from) tys #

(HasUnique rel rels cols, Has col cols ty, bys ~ '['(rel, col)]) => IsLabel col (NP (By rels) bys) Source # 
Instance details

Defined in Squeal.PostgreSQL.Query.Table

Methods

fromLabel :: NP (By rels) bys #

labels ~ '[label] => IsPGlabel label (NP PGlabel labels) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.Schema

Methods

label :: NP PGlabel labels Source #

All (Compose Eq f) xs => Eq (NP f xs) 
Instance details

Defined in Data.SOP.NP

Methods

(==) :: NP f xs -> NP f xs -> Bool #

(/=) :: NP f xs -> NP f xs -> Bool #

(All (Compose Eq f) xs, All (Compose Ord f) xs) => Ord (NP f xs) 
Instance details

Defined in Data.SOP.NP

Methods

compare :: NP f xs -> NP f xs -> Ordering #

(<) :: NP f xs -> NP f xs -> Bool #

(<=) :: NP f xs -> NP f xs -> Bool #

(>) :: NP f xs -> NP f xs -> Bool #

(>=) :: NP f xs -> NP f xs -> Bool #

max :: NP f xs -> NP f xs -> NP f xs #

min :: NP f xs -> NP f xs -> NP f xs #

All (Compose Show f) xs => Show (NP f xs) 
Instance details

Defined in Data.SOP.NP

Methods

showsPrec :: Int -> NP f xs -> ShowS #

show :: NP f xs -> String #

showList :: [NP f xs] -> ShowS #

All (Compose Semigroup f) xs => Semigroup (NP f xs)

Since: sop-core-0.4.0.0

Instance details

Defined in Data.SOP.NP

Methods

(<>) :: NP f xs -> NP f xs -> NP f xs #

sconcat :: NonEmpty (NP f xs) -> NP f xs #

stimes :: Integral b => b -> NP f xs -> NP f xs #

(All (Compose Monoid f) xs, All (Compose Semigroup f) xs) => Monoid (NP f xs)

Since: sop-core-0.4.0.0

Instance details

Defined in Data.SOP.NP

Methods

mempty :: NP f xs #

mappend :: NP f xs -> NP f xs -> NP f xs #

mconcat :: [NP f xs] -> NP f xs #

All (Compose NFData f) xs => NFData (NP f xs)

Since: sop-core-0.2.5.0

Instance details

Defined in Data.SOP.NP

Methods

rnf :: NP f xs -> () #

All KnownSymbol aliases => RenderSQL (NP Alias aliases) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.Alias

Methods

renderSQL :: NP Alias aliases -> ByteString Source #

All KnownSymbol labels => RenderSQL (NP PGlabel labels) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.Schema

Methods

renderSQL :: NP PGlabel labels -> ByteString Source #

type AllZipN (NP :: (k -> Type) -> [k] -> Type) (c :: a -> b -> Constraint) 
Instance details

Defined in Data.SOP.NP

type AllZipN (NP :: (k -> Type) -> [k] -> Type) (c :: a -> b -> Constraint) = AllZip c
type Same (NP :: (k1 -> Type) -> [k1] -> Type) 
Instance details

Defined in Data.SOP.NP

type Same (NP :: (k1 -> Type) -> [k1] -> Type) = NP :: (k2 -> Type) -> [k2] -> Type
type SListIN (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

type SListIN (NP :: (k -> Type) -> [k] -> Type) = SListI :: [k] -> Constraint
type UnProd (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NS

type UnProd (NP :: (k -> Type) -> [k] -> Type) = NS :: (k -> Type) -> [k] -> Type
type Prod (NP :: (k -> Type) -> [k] -> Type) 
Instance details

Defined in Data.SOP.NP

type Prod (NP :: (k -> Type) -> [k] -> Type) = NP :: (k -> Type) -> [k] -> Type
type AllN (NP :: (k -> Type) -> [k] -> Type) (c :: k -> Constraint) 
Instance details

Defined in Data.SOP.NP

type AllN (NP :: (k -> Type) -> [k] -> Type) (c :: k -> Constraint) = All c
type CollapseTo (NP :: (k -> Type) -> [k] -> Type) a 
Instance details

Defined in Data.SOP.NP

type CollapseTo (NP :: (k -> Type) -> [k] -> Type) a = [a]

(*:) :: f x -> f y -> NP f '[x, y] infixl 8 Source #

A useful operator for ending an NP list of length at least 2 without Nil

one :: f x -> NP f '[x] Source #

A list of length one.

Path

data Path (p :: k -> k -> Type) (x :: k) (y :: k) where #

A Path with steps in p is a singly linked list of "type-aligned" constructions of p.

>>> :{
let
  path :: Path (->) String Int
  path = length :>> (\x -> x^2) :>> Done
in
  qfold path "hello"
:}
25

Constructors

Done :: forall k (p :: k -> k -> Type) (x :: k). Path p x x 
(:>>) :: forall k (p :: k -> k -> Type) (x :: k) (y1 :: k) (y :: k). p x y1 -> Path p y1 y -> Path p x y infixr 7 

Instances

Instances details
QFunctor (Path :: (k -> k -> Type) -> k -> k -> Type) 
Instance details

Defined in Control.Category.Free

Methods

qmap :: forall p q (x :: k2) (y :: k3). (forall (x1 :: k0) (y1 :: k1). p x1 y1 -> q x1 y1) -> Path p x y -> Path q x y #

QPointed (Path :: (k -> k -> Type) -> k -> k -> Type) 
Instance details

Defined in Control.Category.Free

Methods

qsingle :: forall p (x :: k0) (y :: k1). p x y -> Path p x y #

QMonad (Path :: (k -> k -> Type) -> k -> k -> Type) 
Instance details

Defined in Control.Category.Free

Methods

qjoin :: forall (p :: k0 -> k1 -> Type) (x :: k0) (y :: k1). Path (Path p) x y -> Path p x y #

qbind :: forall p (q :: k0 -> k1 -> Type) (x :: k0) (y :: k1). (forall (x1 :: k0) (y1 :: k1). p x1 y1 -> Path q x1 y1) -> Path p x y -> Path q x y #

CFree (Path :: (k -> k -> Type) -> k -> k -> Type) 
Instance details

Defined in Control.Category.Free

QFoldable (Path :: (k -> k -> Type) -> k -> k -> Type) 
Instance details

Defined in Control.Category.Free

Methods

qfoldMap :: forall q p (x :: k0) (y :: k0). Category q => (forall (x1 :: k0) (y1 :: k0). p x1 y1 -> q x1 y1) -> Path p x y -> q x y #

qfold :: forall q (x :: k0) (y :: k0). Category q => Path q x y -> q x y #

qfoldr :: forall k1 p q (y :: k0) (z :: k1) (x :: k0). (forall (x1 :: k0) (y1 :: k0) (z1 :: k1). p x1 y1 -> q y1 z1 -> q x1 z1) -> q y z -> Path p x y -> q x z #

qfoldl :: forall k1 q p (x :: k1) (y :: k0) (z :: k0). (forall (x1 :: k1) (y1 :: k0) (z1 :: k0). q x1 y1 -> p y1 z1 -> q x1 z1) -> q x y -> Path p y z -> q x z #

qtoMonoid :: forall m p (x :: k0) (y :: k0). Monoid m => (forall (x1 :: k0) (y1 :: k0). p x1 y1 -> m) -> Path p x y -> m #

qtoList :: forall p a (x :: k0) (y :: k0). (forall (x1 :: k0) (y1 :: k0). p x1 y1 -> a) -> Path p x y -> [a] #

qtraverse_ :: forall m q p (x :: k0) (y :: k0). (Applicative m, Category q) => (forall (x1 :: k0) (y1 :: k0). p x1 y1 -> m (q x1 y1)) -> Path p x y -> m (q x y) #

QTraversable (Path :: (k -> k -> Type) -> k -> k -> Type) 
Instance details

Defined in Control.Category.Free

Methods

qtraverse :: forall m p q (x :: k0) (y :: k0). Applicative m => (forall (x1 :: k0) (y1 :: k0). p x1 y1 -> m (q x1 y1)) -> Path p x y -> m (Path q x y) #

Category (Path p :: k -> k -> Type) 
Instance details

Defined in Control.Category.Free

Methods

id :: forall (a :: k0). Path p a a #

(.) :: forall (b :: k0) (c :: k0) (a :: k0). Path p b c -> Path p a b -> Path p a c #

(KnownSymbol cte, with1 ~ ((cte ::: common) ': with)) => Aliasable cte (statement with db params common) (Path (CommonTableExpression statement db params) with with1) Source # 
Instance details

Defined in Squeal.PostgreSQL.Query.With

Methods

as :: statement with db params common -> Alias cte -> Path (CommonTableExpression statement db params) with with1 Source #

(forall (x1 :: k) (y1 :: k). Show (p x1 y1)) => Show (Path p x y) 
Instance details

Defined in Control.Category.Free

Methods

showsPrec :: Int -> Path p x y -> ShowS #

show :: Path p x y -> String #

showList :: [Path p x y] -> ShowS #

x ~ y => Semigroup (Path p x y) 
Instance details

Defined in Control.Category.Free

Methods

(<>) :: Path p x y -> Path p x y -> Path p x y #

sconcat :: NonEmpty (Path p x y) -> Path p x y #

stimes :: Integral b => b -> Path p x y -> Path p x y #

x ~ y => Monoid (Path p x y) 
Instance details

Defined in Control.Category.Free

Methods

mempty :: Path p x y #

mappend :: Path p x y -> Path p x y -> Path p x y #

mconcat :: [Path p x y] -> Path p x y #

Type Level List

type family Join xs ys where ... Source #

Join is simply promoted ++ and is used in JOINs in FromClauses.

Equations

Join '[] ys = ys 
Join (x ': xs) ys = x ': Join xs ys 

disjoin :: forall xs ys expr. SListI xs => NP expr (Join xs ys) -> (NP expr xs, NP expr ys) Source #

disjoin is a utility function for splitting an NP list into pieces.

class Additional expr where Source #

The Additional class is for appending type-level list parameterized constructors such as NP, Selection, and FromClause.

Methods

also :: expr ys -> expr xs -> expr (Join xs ys) Source #

Instances

Instances details
Additional (NP expr :: [a] -> Type) Source # 
Instance details

Defined in Squeal.PostgreSQL.Type.List

Methods

also :: forall (ys :: [a0]) (xs :: [a0]). NP expr ys -> NP expr xs -> NP expr (Join xs ys) Source #

Additional (FromClause lat with db params :: FromType -> Type) Source # 
Instance details

Defined in Squeal.PostgreSQL.Query.From

Methods

also :: forall (ys :: [a]) (xs :: [a]). FromClause lat with db params ys -> FromClause lat with db params xs -> FromClause lat with db params (Join xs ys) Source #

Additional (Selection grp lat with db params from :: RowType -> Type) Source # 
Instance details

Defined in Squeal.PostgreSQL.Query.Select

Methods

also :: forall (ys :: [a]) (xs :: [a]). Selection grp lat with db params from ys -> Selection grp lat with db params from xs -> Selection grp lat with db params from (Join xs ys) Source #

type family Elem x xs where ... Source #

Elem is a promoted elem.

Equations

Elem x '[] = 'False 
Elem x (x ': _) = 'True 
Elem x (_ ': xs) = Elem x xs 

type family In x xs :: Constraint where ... Source #

In x xs is a constraint that proves that x is in xs.

Equations

In x xs = If (Elem x xs) (() :: Constraint) (TypeError (('ShowType x :<>: 'Text " is not in ") :<>: 'ShowType xs)) 

type family Length (xs :: [k]) :: Nat where ... Source #

Calculate the Length of a type level list

>>> :kind! Length '[Char,String,Bool,Double]
Length '[Char,String,Bool,Double] :: Nat
= 4

Equations

Length '[] = 0 
Length (_ ': xs) = 1 + Length xs 

type family SubList (xs :: [k]) (ys :: [k]) :: Bool where ... Source #

SubList checks that one type level list is a sublist of another, with the same ordering.

>>> :kind! SubList '[1,2,3] '[4,5,6]
SubList '[1,2,3] '[4,5,6] :: Bool
= 'False
>>> :kind! SubList '[1,2,3] '[1,2,3,4]
SubList '[1,2,3] '[1,2,3,4] :: Bool
= 'True
>>> :kind! SubList '[1,2,3] '[0,1,0,2,0,3]
SubList '[1,2,3] '[0,1,0,2,0,3] :: Bool
= 'True
>>> :kind! SubList '[1,2,3] '[3,2,1]
SubList '[1,2,3] '[3,2,1] :: Bool
= 'False

Equations

SubList '[] ys = 'True 
SubList (x ': xs) '[] = 'False 
SubList (x ': xs) (x ': ys) = SubList xs ys 
SubList (x ': xs) (y ': ys) = SubList (x ': xs) ys 

type family SubsetList (xs :: [k]) (ys :: [k]) :: Bool where ... Source #

SubsetList checks that one type level list is a subset of another, regardless of ordering and repeats.

>>> :kind! SubsetList '[1,2,3] '[4,5,6]
SubsetList '[1,2,3] '[4,5,6] :: Bool
= 'False
>>> :kind! SubsetList '[1,2,3] '[1,2,3,4]
SubsetList '[1,2,3] '[1,2,3,4] :: Bool
= 'True
>>> :kind! SubsetList '[1,2,3] '[0,1,0,2,0,3]
SubsetList '[1,2,3] '[0,1,0,2,0,3] :: Bool
= 'True
>>> :kind! SubsetList '[1,2,3] '[3,2,1]
SubsetList '[1,2,3] '[3,2,1] :: Bool
= 'True
>>> :kind! SubsetList '[1,1,1] '[3,2,1]
SubsetList '[1,1,1] '[3,2,1] :: Bool
= 'True

Equations

SubsetList '[] ys = 'True 
SubsetList (x ': xs) ys = Elem x ys && SubsetList xs ys 

Type Level Sort

type Sort ls = MergeSort (Twos ls) Source #

Sort sorts a type level list of Symbols in ascending lexicographic order

type family MergeSort (ls :: [[Symbol]]) :: [Symbol] where ... Source #

MergeSort is the workhorse behind Sort

Equations

MergeSort '[] = '[] 
MergeSort '[x] = x 
MergeSort ls = MergeSort (FoldMerge ls) 

type family Twos (ls :: [k]) :: [[k]] where ... Source #

Twos splits a type-level list into a list of sorted lists of length 2 (with a singelton list potentially at the end) It is required for implementing MergeSort

Equations

Twos (x ': (y ': rs)) = Merge '[x] '[y] ': Twos rs 
Twos '[x] = '['[x]] 
Twos '[] = '[] 

type family FoldMerge (ls :: [[Symbol]]) :: [[Symbol]] where ... Source #

FoldMerge folds over a list of sorted lists, merging them into a single sorted list

Equations

FoldMerge (x ': (y ': rs)) = Merge x y ': FoldMerge rs 
FoldMerge '[x] = '[x] 
FoldMerge '[] = '[] 

type family Merge (ls :: [Symbol]) (rs :: [Symbol]) :: [Symbol] where ... Source #

Merge two sorted lists into one list

Equations

Merge '[] r = r 
Merge l '[] = l 
Merge (l ': ls) (r ': rs) = MergeHelper (l ': ls) (r ': rs) (CmpSymbol l r) 

type family MergeHelper (ls :: [Symbol]) (rs :: [Symbol]) (cmp :: Ordering) where ... Source #

MergeHelper decides whether to take an element from the right or left list next, depending on the result of their comparison

Equations

MergeHelper ls (r ': rs) 'GT = r ': Merge ls rs 
MergeHelper (l ': ls) rs leq = l ': Merge ls rs 

type family MapFst (ls :: [(j, k)]) :: [j] where ... Source #

MapFst takes the first value of each tuple of a type level list of tuples. Useful for getting only the names in associatve lists

Equations

MapFst ('(j, _) ': rest) = j ': MapFst rest 
MapFst '[] = '[]