-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTuple.hs
53 lines (46 loc) · 1.54 KB
/
Tuple.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
{-|
Module : Examples.Tuple
Description : An example of tuple projection.
Copyright : (c) Alexander Vieth, 2015
Licence : BSD3
Maintainer : [email protected]
Stability : experimental
Portability : non-portable (GHC only)
-}
{-# LANGUAGE AutoDeriveTypeable #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TypeOperators #-}
module Examples.Tuple where
import Prelude hiding ((.), id)
import Control.Arrow
import Control.Category
import Data.List.NonEmpty
import Data.Algebraic.Index
import Data.Algebraic.Product
import Data.Algebraic.Function
-- | In order to make a total surjection onto (), we must be able to enumerate
-- the entire domain type, as the entire type is the preimage of ().
terminalSurjection
:: forall a .
( Enum a, Bounded a )
=> F Total Surjection a ()
terminalSurjection = F fto ffrom
where
fto :: Total a ()
fto = arr (const ())
ffrom :: Surjection () a
ffrom = Kleisli (\() -> minBound :| [succ minBound..])
-- | If the domain is not enumerable and bounded, we can't obtain a surjection,
-- so we must settle for an F which is not reversible.
terminal :: F Total EmptyArrow a ()
terminal = F fto ffrom
where
fto :: Total a ()
fto = arr (const ())
ffrom :: EmptyArrow () a
ffrom = EmptyArrow
projectFirst :: (Enum b, Bounded b) => F Total Surjection (a :*: b) a
projectFirst = eliminateTerm two <.> productF (identity .*. terminalSurjection)
-- | runKleisli (from example) 1 = (1, True) :| (1, False)
example :: F Total Surjection (Int :*: Bool) Int
example = projectFirst