Skip to content
Open
Show file tree
Hide file tree
Changes from 23 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
24d71e1
Clean up Monad Type
FintanH Feb 2, 2019
c21b644
Add flipEither and hush
FintanH Feb 2, 2019
8460fbb
Use [] annotation for None
FintanH Feb 2, 2019
333e454
Add base type class for Compactable and from functions
FintanH Feb 2, 2019
74b40fa
Use None instead of []
FintanH Feb 2, 2019
c0eaf24
Run linter
FintanH Feb 2, 2019
bb8dbd5
Add Compactable combinators
FintanH Feb 2, 2019
53e0a1f
Use anonymous tuple syntax
FintanH Feb 2, 2019
86b5f2a
Clean up compactable representation
FintanH Feb 2, 2019
eb27c3c
List compactable instance
FintanH Feb 2, 2019
5473be0
Fix fromCompact
FintanH Feb 2, 2019
9e30147
Add Optional instance
FintanH Feb 2, 2019
8dca13e
Added Either instance
FintanH Feb 2, 2019
b744ae7
Rename Maybe to Optional
FintanH Feb 2, 2019
ad3b3fa
Fix fromCompact and annotate instances
FintanH Feb 2, 2019
d91d645
Document Compactable/Type
FintanH Feb 2, 2019
4e105fd
Document from functions
FintanH Feb 2, 2019
c89d4c4
Fix spacing, add docs and examples to map and ap functions
FintanH Feb 2, 2019
582df5e
Fix ap docs
FintanH Feb 2, 2019
f83ae86
Add bind docs
FintanH Feb 2, 2019
780de73
Document flipEither and hush
FintanH Feb 2, 2019
12ee10e
Make typeclass method be mapOptional and mapEither
FintanH Feb 4, 2019
598e210
Only use mapOptional. Clean up definitions
FintanH Feb 4, 2019
74036eb
Update docs and found some type errors
FintanH Feb 5, 2019
9205845
Merge branch 'master' into fintan/compactable
FintanH Feb 14, 2019
7429abc
Move flipEither to flip. Remove not needed doc
FintanH Feb 16, 2019
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Compactable/Type
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
{-

Compactable serves as an abstraction over filtering and partitioning, using two functions
compact and separate, respectively.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This makes it sound like the type class still has multiple methods. I would rewrite this to discuss mapOptional instead, and then move the other comments to the respective expressions.


Both functions work over some higher kind f (Type -> Type).

compact works over the f when it is fully applied with an Optional type. It filters out None
values, leaving only the values contained in the Some values.

separate works over the f when it is fully applied with an Either type. It partitions Left
values to the _1 element of a tuple, and Right values to the _2 element of a tuple.

Since both functions can be written in terms of the other, we can create instances by choosing one
of the function fromCompact or fromSeparate.

-}
λ(f : Type → Type)
→ { mapOptional : ∀(a : Type) → ∀(b : Type) → (a → Optional b) → f a → f b }
30 changes: 30 additions & 0 deletions Compactable/apEither
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{-
apEither maps an `f` of functions to Eithers over the `f a` and `separate`s `Left`s from `Right`s.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of apEither in the comment here.


let E = constructors (./Either/Type Natural Natural)

in ./Compactable/apEither
List
./List/compactable
./List/applicative
Natural
Natural
[ λ(n : Natural) → if Natural/even n then E.Left n else E.Right n
, λ(n : Natural) → if Natural/odd n then E.Left n else E.Right n
]
[ 0, 1, 2, 3, 4, 5 ]
= { _1 = [ 0, 2, 4, 1, 3, 5 ], _2 = [ 1, 3, 5, 0, 2, 4 ] }

-}
let Applicative = ./../Applicative/Type

in let Either = ./../Either/Type

in λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(applicative : Applicative f)
→ λ(a : Type)
→ λ(b : Type)
→ λ(k : f (a → Either a b))
→ λ(fa : f a)
→ ./separate f c a b (applicative.ap a (Either a b) k fa)
31 changes: 31 additions & 0 deletions Compactable/apOptional
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{-

apOptional maps a `f` of functions to Optionals over the `f` and `compact`s away the `None` values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get rid of “apOptional” here.


Examples:

```
./Compactable/apOptional
List
./List/compactable
./List/applicative
Natural
Natural
[ λ(n : Natural) → if Natural/even n then Some n else None Natural
, λ(n : Natural) → if Natural/odd n then Some n else None Natural
]
[ 0, 1, 2, 3, 4, 5 ]
= [ 0, 2, 4, 1, 3, 5 ]
```

-}
let Applicative = ./../Applicative/Type

in λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(applicative : Applicative f)
→ λ(a : Type)
→ λ(b : Type)
→ λ(k : f (a → Optional b))
→ λ(fa : f a)
→ ./compact f c b (applicative.ap a (Optional b) k fa)
44 changes: 44 additions & 0 deletions Compactable/bindEither
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
{-

bindEither binds to a `f` of Optional over the `f a` and `separate`s `Left`s and `Right`s.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same, etc. for other files.


Examples:

```
let replicate =
https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/List/replicate

in let Either = ./Either/Type

in let E = constructors (Either Natural Natural)

in ./Compactable/bindEither
List
./List/compactable
./List/monad
Natural
Natural
( λ(n : Natural)
→ if Natural/even n

then replicate n (Either Natural Natural) (E.Left n)

else replicate n (Either Natural Natural) (E.Right n)
)
[ 0, 1, 2, 3, 4, 5 ]
= { _1 = [ 2, 2, 4, 4, 4, 4 ], _2 = [ 1, 3, 3, 3, 5, 5, 5, 5, 5 ] }
```

-}
let Monad = ./../Monad/Type

in let Either = ./../Either/Type

in λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(monad : Monad f)
→ λ(a : Type)
→ λ(b : Type)
→ λ(k : a → f (Either a b))
→ λ(fa : f a)
→ ./separate f c a b (monad.bind a (Either a b) fa k)
38 changes: 38 additions & 0 deletions Compactable/bindOptional
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
{-

bindOptional binds to a `f` of Optional over the `f a` and `compact`s away the `None` values.

Examples:

```
let replicate =
https://raw.githubusercontent.com/dhall-lang/dhall-lang/master/Prelude/List/replicate

in ./Compactable/bindOptional
List
./List/compactable
./List/monad
Natural
Natural
( λ(n : Natural)
→ if Natural/even n

then replicate n (Optional Natural) (Some n)

else [] : List (Optional Natural)
)
[ 0, 1, 2, 3, 4, 5 ]
= [ 2, 2, 4, 4, 4, 4 ]
```

-}
let Monad = ./../Monad/Type

in λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(monad : Monad f)
→ λ(a : Type)
→ λ(b : Type)
→ λ(k : a → f (Optional b))
→ λ(fa : f a)
→ ./compact f c b (monad.bind a (Optional b) fa k)
23 changes: 23 additions & 0 deletions Compactable/compact
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{-

mapOptional maps a function to Optionals over the `f` and `compact`s away the `None` values.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This claims to be mapOptional, but isn’t.


Examples:

```
./Compactable/mapOptional
List
./List/compactable
./List/functor
Natural
Natural
(λ(n : Natural) → if Natural/even n then Some n else None Natural)
[ 1, 2, 3, 4, 5 ]
= [ 2, 4 ]
```

-}
λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(a : Type)
→ c.mapOptional (Optional a) a ((./../Function/category).identity (Optional a))
49 changes: 49 additions & 0 deletions Compactable/separate
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
{-

mapEither maps a function to Either over the `f` and `separate`s `Left`s from `Right`s.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This says mapEither, but the file is separate. I would change this comment to say something like “This expression maps …” to make it less likely to get out of sync.


Examples:

```
let E = constructors (./Either/Type Natural Natural)

in ./Compactable/mapEither
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here. Obviously harder to avoid the name. I guess we need like dhall-doctest now, right 😁

List
./List/compactable
./List/functor
Natural
Natural
(λ(n : Natural) → if Natural/even n then E.Left n else E.Right n)
[ 1, 2, 3, 4, 5 ]
= { _1 = [ 2, 4 ], _2 = [ 1, 3, 5 ] }
```

-}
let Either = ./../Either/Type

in let compose = (./../Function/category).compose

in let hush = ./../Either/hush

in let flipEither = ./../Either/flipEither

in λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(l : Type)
→ λ(r : Type)
→ λ(fa : f (Either l r))
→ { _1 =
c.mapOptional
(Either l r)
l
( compose
(Either l r)
(Either r l)
(Optional l)
(hush r l)
(flipEither l r)
)
fa
, _2 =
c.mapOptional (Either l r) r (hush l r) fa
}
20 changes: 20 additions & 0 deletions Compactable/traverseEither
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
let Traversable = ./../Traversable/Type

in let Applicative = ./../Applicative/Type

in let Either = ./../Either/Type

in λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(traversable : Traversable f)
→ λ(g : Type → Type)
→ λ(applicative : Applicative g)
→ λ(a : Type)
→ λ(b : Type)
→ λ(k : a → g (Either a b))
→ λ(fa : f a)
→ applicative.map
(f (Either a b))
{ _1 : f a, _2 : f b }
(./separate f c a b)
(traversable.traverse g applicative a (Either a b) k fa)
18 changes: 18 additions & 0 deletions Compactable/traverseOptional
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
let Traversable = ./../Traversable/Type

in let Applicative = ./../Applicative/Type

in λ(f : Type → Type)
→ λ(c : ./Type f)
→ λ(traversable : Traversable f)
→ λ(g : Type → Type)
→ λ(applicative : Applicative g)
→ λ(a : Type)
→ λ(b : Type)
→ λ(k : a → g (Optional b))
→ λ(fa : f a)
→ applicative.map
(f (Optional b))
(f b)
(./compact f c b)
(traversable.traverse g applicative a (Optional b) k fa)
31 changes: 31 additions & 0 deletions Either/compactable
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
{-
mapOptional : (a -> Optional b) -> Either m a -> Either m b
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don’t think this is useful documentation, especially since this is a type class instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching, I actually just put it there to help me implement it 😅

-}
let Either = ./Type

in let Monoid = ./../Monoid/Type

in λ(m : Type)
→ λ(monoid : Monoid m)
→ { mapOptional =
λ(a : Type)
→ λ(b : Type)
→ λ(k : a → Optional b)
→ λ(either : Either m a)
→ let E = constructors (Either m b)

in merge
{ Left =
λ(x : m) → E.Left x
, Right =
λ(y : a)
→ Optional/fold
b
(k y)
(Either m b)
E.Right
(E.Left monoid.unit)
}
either
}
: ./../Compactable/Type (Either m)
30 changes: 30 additions & 0 deletions Either/flipEither
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
{-

Flip the value of an Either where `Right` goes to `Left`, and `Left` goes to `Right`.

Examples:
```
let Either = ./Either/Type

in let E = constructors (Either Text Natural)

in ./Either/flipEither Text Natural (E.Left "ohno")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should probably just rename this to flip. Also, it’s probably type-classable, like Bifunctor-ish?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've leave it for now though and just rename to flip

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, Either isn't an instance. Need to keep looking :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

= < Right = "ohno" | Left : Natural >


let Either = ./Either/Type

in let E = constructors (Either Text Natural)

in ./Either/flipEither Text Natural (E.Right 42)
= < Left = 42 | Right : Text >
```

-}
let Either = ./Type

in λ(a : Type)
→ λ(b : Type)
→ let E = constructors (Either b a)

in ./fold a b (Either b a) E.Right E.Left
27 changes: 27 additions & 0 deletions Either/hush
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
{-

Turns an `Either a b` into an `Optional b` by hushing `Left` values to `None` and
converting `Right` values to `Some`.

Examples:
```
let Either = ./Either/Type

in let E = constructors (Either Text Natural)

in ./Either/hush Text Natural (E.Right 42)
= Some 42


let Either = ./Either/Type

in let E = constructors (Either Text Natural)

in ./Either/hush Text Natural (E.Left "ohno")
= None Natural
```

-}
λ(a : Type)
→ λ(b : Type)
→ ./fold a b (Optional b) (λ(_ : a) → None b) (λ(x : b) → Some x)
2 changes: 1 addition & 1 deletion Either/lefts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@
in λ(a : Type)
→ λ(b : Type)
→ λ(eithers : List (Either a b))
→ (./partition a b eithers).lefts
→ (./partition a b eithers)._1
Loading