Copyright | (c) Yusuke Matsushita 2014 |
---|---|
License | BSD3 |
Maintainer | Yusuke Matsushita |
Stability | provisional |
Portability | portable |
Safe Haskell | Trustworthy |
Language | Haskell2010 |
Basic tools for clusses. Examples show how to use them.
Template haskell tools are in the module Type.Cluss.TH.
- class In as a where
- type family Has as a :: Bool
- data Type a
- data AnyType p
- data a <| p
- type Unary a p = a <| p
- type Binary a p = a <| p
- type Ternary a p = a <| p
- type Quaternary a p = a <| p
- type Quinary a p = a <| p
- type Senary a p = a <| p
- type Septenary a p = a <| p
- type Octary a p = a <| p
- type Nonary a p = a <| p
- type Denary a p = a <| p
- type AllOf as = AllOf' as as
- data family AllOf' ts as t
- class (True ~ False) => This a
- class Pure a
- type Is = (~)
- class (p a, q a) => (p >+< q) a
- class (p a b, q a b) => (p >++< q) a b
- class (p a b c, q a b c) => (p >+++< q) a b c
- class (p a b c d, q a b c d) => (p >++++< q) a b c d
- class (p a b c d e, q a b c d e) => (p >+++++< q) a b c d e
- class (p a b c d e f, q a b c d e f) => (p >++++++< q) a b c d e f
- class (p a b c d e f g, q a b c d e f g) => (p >+++++++< q) a b c d e f g
- class (p a b c d e f g h, q a b c d e f g h) => (p >++++++++< q) a b c d e f g h
- class (p a b c d e f g h i, q a b c d e f g h i) => (p >+++++++++< q) a b c d e f g h i
- class (p a b c d e f g h i j, q a b c d e f g h i j) => (p >++++++++++< q) a b c d e f g h i j
- class (p a, q b) => (p >|< q) a b
- class (p a b, q c) => (p >||< q) a b c
- class (p a b c, q d) => (p >|||< q) a b c d
- class (p a b c d, q e) => (p >||||< q) a b c d e
- class (p a b c d e, q f) => (p >|||||< q) a b c d e f
- class (p a b c d e f, q g) => (p >||||||< q) a b c d e f g
- class (p a b c d e f g, q h) => (p >|||||||< q) a b c d e f g h
- class (p a b c d e f g h, q i) => (p >||||||||< q) a b c d e f g h i
- class (p a b c d e f g h i, q j) => (p >|||||||||< q) a b c d e f g h i j
- class p a => IR1 p a
- class p a b => IR2 p a b
- class p a b c => IR3 p a b c
- class p a b c d => IR4 p a b c d
- class p a b c d e => IR5 p a b c d e
- class p a b c d e f => IR6 p a b c d e f
- class p a b c d e f g => IR7 p a b c d e f g
- class p a b c d e f g h => IR8 p a b c d e f g h
- class p a b c d e f g h i => IR9 p a b c d e f g h i
- class p a b c d e f g h i j => IR10 p a b c d e f g h i j
- type AllOfI as = AllOfI' as as
- andI :: a -> AllOfI' ts as -> AllOfI' ts (Type a : as)
- andI1 :: (forall b. Modify (a b) (In ts) p b => a b) -> AllOfI' ts as -> AllOfI' ts (Unary a p : as)
- andI2 :: (forall b c. Modify2 (a b c) (In ts) p b c => a b c) -> AllOfI' ts as -> AllOfI' ts (Binary a p : as)
- andI3 :: (forall b c d. Modify3 (a b c d) (In ts) p b c d => a b c d) -> AllOfI' ts as -> AllOfI' ts (Ternary a p : as)
- andI4 :: (forall b c d e. Modify4 (a b c d e) (In ts) p b c d e => a b c d e) -> AllOfI' ts as -> AllOfI' ts (Quaternary a p : as)
- andI5 :: (forall b c d e f. Modify5 (a b c d e f) (In ts) p b c d e f => a b c d e f) -> AllOfI' ts as -> AllOfI' ts (Quinary a p : as)
- andI6 :: (forall b c d e f g. Modify6 (a b c d e f g) (In ts) p b c d e f g => a b c d e f g) -> AllOfI' ts as -> AllOfI' ts (Senary a p : as)
- andI7 :: (forall b c d e f g h. Modify7 (a b c d e f g h) (In ts) p b c d e f g h => a b c d e f g h) -> AllOfI' ts as -> AllOfI' ts (Septenary a p : as)
- andI8 :: (forall b c d e f g h i. Modify8 (a b c d e f g h i) (In ts) p b c d e f g h i => a b c d e f g h i) -> AllOfI' ts as -> AllOfI' ts (Octary a p : as)
- andI9 :: (forall b c d e f g h i j. Modify9 (a b c d e f g h i j) (In ts) p b c d e f g h i j => a b c d e f g h i j) -> AllOfI' ts as -> AllOfI' ts (Nonary a p : as)
- andI10 :: (forall b c d e f g h i j k. Modify10 (a b c d e f g h i j k) (In ts) p b c d e f g h i j k => a b c d e f g h i j k) -> AllOfI' ts as -> AllOfI' ts (Denary a p : as)
- noneI :: AllOfI' ts []
- projI :: In as a => AllOfI as -> a
- type AllOfF as t = AllOfF' as as t
- andF :: (a -> t) -> AllOfF' ts as t -> AllOfF' ts (Type a : as) t
- andF1 :: (forall b. Modify (a b) (In ts) p b => a b -> t) -> AllOfF' ts as t -> AllOfF' ts (Unary a p : as) t
- andF2 :: (forall b c. Modify2 (a b c) (In ts) p b c => a b c -> t) -> AllOfF' ts as t -> AllOfF' ts (Binary a p : as) t
- andF3 :: (forall b c d. Modify3 (a b c d) (In ts) p b c d => a b c d -> t) -> AllOfF' ts as t -> AllOfF' ts (Ternary a p : as) t
- andF4 :: (forall b c d e. Modify4 (a b c d e) (In ts) p b c d e => a b c d e -> t) -> AllOfF' ts as t -> AllOfF' ts (Quaternary a p : as) t
- andF5 :: (forall b c d e f. Modify5 (a b c d e f) (In ts) p b c d e f => a b c d e f -> t) -> AllOfF' ts as t -> AllOfF' ts (Quinary a p : as) t
- andF6 :: (forall b c d e f g. Modify6 (a b c d e f g) (In ts) p b c d e f g => a b c d e f g -> t) -> AllOfF' ts as t -> AllOfF' ts (Senary a p : as) t
- andF7 :: (forall b c d e f g h. Modify7 (a b c d e f g h) (In ts) p b c d e f g h => a b c d e f g h -> t) -> AllOfF' ts as t -> AllOfF' ts (Septenary a p : as) t
- andF8 :: (forall b c d e f g h i. Modify8 (a b c d e f g h i) (In ts) p b c d e f g h i => a b c d e f g h i -> t) -> AllOfF' ts as t -> AllOfF' ts (Octary a p : as) t
- andF9 :: (forall b c d e f g h i j. Modify9 (a b c d e f g h i j) (In ts) p b c d e f g h i j => a b c d e f g h i j -> t) -> AllOfF' ts as t -> AllOfF' ts (Nonary a p : as) t
- andF10 :: (forall b c d e f g h i j k. Modify10 (a b c d e f g h i j k) (In ts) p b c d e f g h i j k => a b c d e f g h i j k -> t) -> AllOfF' ts as t -> AllOfF' ts (Denary a p : as) t
- noneF :: AllOfF' ts [] t
- projF :: In as a => AllOfF as t -> a -> t
Clusses
is a cluss, where In
asas
is a list of type patterns.
Normally, as
is concrete and does not contain any type variables, like
.
In
[Binary
(->) (Show
>|< This
), Type
String
] a
When a
satisfies In as a
, you can use the method
.
proj
:: AllOf
as f -> f a
Internally, "type pattern matching" is executed by Where, a closed type family, which cannot check if a type satisfies a constraint.
If as
has many type patterns that can match a
, only the first one matches a
.
Clusses call for some language extensions. Basically, this language pragma will do.
{-# LANGUAGE DataKinds, FlexibleContexts, TypeOperators #-}
In' k (Where k as as a) as as a => In k as a |
type family Has as a :: Bool Source
judges whether a type Has
as aa
belongs to a cluss
, on some level.
When not sure, In
asHas
always returns True
.
For example, when as
has
and Unary
[] Show
a
is [b]
,
Has
can't judge if b
belongs to Show
since the instances of Show
is open,
but it assumes that b
belongs to Show
and
returns True
.
type Has k as a |
Type Patterns
Type patterns are used in the type list (first parameter) of In
.
Each type pattern corresponds to the head of an instance declaration for a type class, namely, instance ... where
.
The empty type
is a type pattern,
where AnyType
pp
is a type function from a type to a constraint.
The type pattern
basically corresponds to AnyType
Show
instance
(where Show
a => C a where ...C
is a corresponding type class), for example,
but AnyType
is much more useful
in that it does not cause overlapping instances whereas C
is likely to,
because cluss instances are prioritized.
The empty type a
is a type pattern,
where <|
pa
is a type constructor,
and p
is a type function to a constraint from the type variables for the constructor a
.
The type pattern [] <|
corresponds to Show
instance
(where Show
a => C [a] where ...C
is a corresponding type class), for example.
You can replace Unary
, Binary
, ..., and Denary
with <|
,
but you can sometimes save the effort of annotating kinds
using Unary
, Binary
, ..., or Denary
instead of <|
,
especially when using the PolyKinds
extension,
because the kinds of the parameters in Unary
, Binary
, ..., and Denary
are restricted as described below.
data AllOf' k ts ((:) * (Denary k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k a p) as) = And10 (forall b c d e f g h i j k. Modify10 k k k k k k k k k k k (a b c d e f g h i j k) (In k ts) p b c d e f g h i j k => t (a b c d e f g h i j k)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Nonary k1 k2 k3 k4 k5 k6 k7 k8 k9 k a p) as) = And9 (forall b c d e f g h i j. Modify9 k k k k k k k k k k (a b c d e f g h i j) (In k ts) p b c d e f g h i j => t (a b c d e f g h i j)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Octary k1 k2 k3 k4 k5 k6 k7 k8 k a p) as) = And8 (forall b c d e f g h i. Modify8 k k k k k k k k k (a b c d e f g h i) (In k ts) p b c d e f g h i => t (a b c d e f g h i)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Septenary k1 k2 k3 k4 k5 k6 k7 k a p) as) = And7 (forall b c d e f g h. Modify7 k k k k k k k k (a b c d e f g h) (In k ts) p b c d e f g h => t (a b c d e f g h)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Senary k1 k2 k3 k4 k5 k6 k a p) as) = And6 (forall b c d e f g. Modify6 k k k k k k k (a b c d e f g) (In k ts) p b c d e f g => t (a b c d e f g)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Quinary k1 k2 k3 k4 k5 k a p) as) = And5 (forall b c d e f. Modify5 k k k k k k (a b c d e f) (In k ts) p b c d e f => t (a b c d e f)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Quaternary k1 k2 k3 k4 k a p) as) = And4 (forall b c d e. Modify4 k k k k k (a b c d e) (In k ts) p b c d e => t (a b c d e)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Ternary k1 k2 k3 k a p) as) = And3 (forall b c d. Modify3 k k k k (a b c d) (In k ts) p b c d => t (a b c d)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Binary k1 k2 k a p) as) = And2 (forall b c. Modify2 k k k (a b c) (In k ts) p b c => t (a b c)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Unary k1 k a p) as) = And1 (forall b. Modify k k (a b) (In k ts) p b => t (a b)) (AllOf' k ts as t) |
type Unary a p = a <| p Source
a <| p
, with a
being of the kind i -> k
, and p
of the kind i ->
.
Constraint
type Binary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> k
, and p
of the kind i -> i2 ->
.
Constraint
type Ternary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> k
, and p
of the kind i -> i2 -> i3 ->
.
Constraint
type Quaternary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> i4 -> k
, and p
of the kind i -> i2 -> i3 -> i4 ->
.
Constraint
type Quinary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> i4 -> i5 -> k
, and p
of the kind i -> i2 -> i3 -> i4 -> i5 ->
.
Constraint
type Senary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> k
, and p
of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 ->
.
Constraint
type Septenary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> k
, and p
of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 ->
.
Constraint
type Octary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> k
, and p
of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 ->
.
Constraint
type Nonary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 -> k
, and p
of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 ->
.
Constraint
type Denary a p = a <| p Source
a <| p
, with a
being of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 -> i10 -> k
, and p
of the kind i -> i2 -> i3 -> i4 -> i5 -> i6 -> i7 -> i8 -> i9 -> i10 ->
.
Constraint
Instance Products
type AllOf as = AllOf' as as Source
is a tuple that contains values of the type AllOf
as ff a
,
where a
can be any type that satisfies In as a
.
Each value corresponds to each type pattern,
and the values in
must be in the same order as the type patterns in AllOf
as fas
.
And, And1, And2, ..., and And10 are used to combine the values,
where None must be added at the end.
You have to use And for
,
And1 for Type
a
, And2 for Unary
a p
,
..., and And10 for Binary
a p
.
Denary
a p
data family AllOf' ts as t Source
data AllOf' k ts ([] *) = None | |
data AllOf' k ts ((:) * (Denary k1 k2 k3 k4 k5 k6 k7 k8 k9 k10 k a p) as) = And10 (forall b c d e f g h i j k. Modify10 k k k k k k k k k k k (a b c d e f g h i j k) (In k ts) p b c d e f g h i j k => t (a b c d e f g h i j k)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Nonary k1 k2 k3 k4 k5 k6 k7 k8 k9 k a p) as) = And9 (forall b c d e f g h i j. Modify9 k k k k k k k k k k (a b c d e f g h i j) (In k ts) p b c d e f g h i j => t (a b c d e f g h i j)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Octary k1 k2 k3 k4 k5 k6 k7 k8 k a p) as) = And8 (forall b c d e f g h i. Modify8 k k k k k k k k k (a b c d e f g h i) (In k ts) p b c d e f g h i => t (a b c d e f g h i)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Septenary k1 k2 k3 k4 k5 k6 k7 k a p) as) = And7 (forall b c d e f g h. Modify7 k k k k k k k k (a b c d e f g h) (In k ts) p b c d e f g h => t (a b c d e f g h)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Senary k1 k2 k3 k4 k5 k6 k a p) as) = And6 (forall b c d e f g. Modify6 k k k k k k k (a b c d e f g) (In k ts) p b c d e f g => t (a b c d e f g)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Quinary k1 k2 k3 k4 k5 k a p) as) = And5 (forall b c d e f. Modify5 k k k k k k (a b c d e f) (In k ts) p b c d e f => t (a b c d e f)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Quaternary k1 k2 k3 k4 k a p) as) = And4 (forall b c d e. Modify4 k k k k k (a b c d e) (In k ts) p b c d e => t (a b c d e)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Ternary k1 k2 k3 k a p) as) = And3 (forall b c d. Modify3 k k k k (a b c d) (In k ts) p b c d => t (a b c d)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Binary k1 k2 k a p) as) = And2 (forall b c. Modify2 k k k (a b c) (In k ts) p b c => t (a b c)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Unary k1 k a p) as) = And1 (forall b. Modify k k (a b) (In k ts) p b => t (a b)) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (AnyType k p) as) = AndAny (forall a. p a => t a) (AllOf' k ts as t) | |
data AllOf' k ts ((:) * (Type k a) as) = And (t a) (AllOf' k ts as t) |
Constraint Combinators
Constraint combinators are used in the second parameter of <|, Unary
, Binary
, ..., or Denary
.
Note that each combinator is kind-polymorphic.
Basic Combinators
class (True ~ False) => This a Source
This
creates a recursion.
In other words, This
will work as
itself
when used in the type list (first parameter) In
asas
of In
,
combined with Type
, <|
, Unary
, Binary
, ..., Denary
,
>+<, >++<, ..., >++++++++++<,
>|<, >||<, ..., and >|||||||||<.
Note that This
will not be expanded into
if the condition described above is not satisfied.
For example, In
asThis
in the parameter of AnyType
will not be expanded
because it causes infinite recursion.
Internally, the expansion is executed by Modify, Modify2, ..., and Modify10.
The instance of This
itself cannot be created
since the context
will never be satisfied.
True
~ False
There is no predetermined limit of recursion depth,
but GHC has a fixed-depth recursion stack for safety,
so you may need to increase the stack depth with -fcontext-stack=N
.
Overlaying Combinators
class (p a, q a) => (p >+< q) a infixl 9 Source
(p >+< q) a == (p a, q a)
(p a, q a) => (>+<) k p q a |
class (p a b, q a b) => (p >++< q) a b infixl 9 Source
(p >++< q) a b == (p a b, q a b)
(p a b, q a b) => (>++<) k k p q a b |
class (p a b c, q a b c) => (p >+++< q) a b c infixl 9 Source
(p >+++< q) a b c == (p a b c, q a b c)
(p a b c, q a b c) => (>+++<) k k k p q a b c |
class (p a b c d, q a b c d) => (p >++++< q) a b c d infixl 9 Source
(p >++++< q) a b c d == (p a b c d, q a b c d)
(p a b c d, q a b c d) => (>++++<) k k k k p q a b c d |
class (p a b c d e, q a b c d e) => (p >+++++< q) a b c d e infixl 9 Source
(p >+++++< q) a b c d e == (p a b c d e, q a b c d e)
(p a b c d e, q a b c d e) => (>+++++<) k k k k k p q a b c d e |
class (p a b c d e f, q a b c d e f) => (p >++++++< q) a b c d e f infixl 9 Source
(p >++++++< q) a b c d e f == (p a b c d e f, q a b c d e f)
(p a b c d e f, q a b c d e f) => (>++++++<) k k k k k k p q a b c d e f |
class (p a b c d e f g, q a b c d e f g) => (p >+++++++< q) a b c d e f g infixl 9 Source
(p >+++++++< q) a b c d e f g == (p a b c d e f g, q a b c d e f g)
(p a b c d e f g, q a b c d e f g) => (>+++++++<) k k k k k k k p q a b c d e f g |
class (p a b c d e f g h, q a b c d e f g h) => (p >++++++++< q) a b c d e f g h infixl 9 Source
(p >++++++++< q) a b c d e f g h == (p a b c d e f g h, q a b c d e f g h)
(p a b c d e f g h, q a b c d e f g h) => (>++++++++<) k k k k k k k k p q a b c d e f g h |
class (p a b c d e f g h i, q a b c d e f g h i) => (p >+++++++++< q) a b c d e f g h i infixl 9 Source
(p >+++++++++< q) a b c d e f g h i == (p a b c d e f g h, q a b c d e f g h i)
(p a b c d e f g h i, q a b c d e f g h i) => (>+++++++++<) k k k k k k k k k p q a b c d e f g h i |
class (p a b c d e f g h i j, q a b c d e f g h i j) => (p >++++++++++< q) a b c d e f g h i j infixl 9 Source
(p >++++++++++< q) a b c d e f g h i j == (p a b c d e f g h, q a b c d e f g h i j)
(p a b c d e f g h i j, q a b c d e f g h i j) => (>++++++++++<) k k k k k k k k k k p q a b c d e f g h i j |
Bonding Combinators
class (p a, q b) => (p >|< q) a b infixl 8 Source
(p >|< q) a b == (p a, q b)
(p a, q b) => (>|<) k k p q a b |
class (p a b, q c) => (p >||< q) a b c infixl 8 Source
(p >||< q) a b c == (p a b, q c)
(p a b, q c) => (>||<) k k k p q a b c |
class (p a b c, q d) => (p >|||< q) a b c d infixl 8 Source
(p >|||< q) a b c d == (p a b c, q d)
(p a b c, q d) => (>|||<) k k k k p q a b c d |
class (p a b c d, q e) => (p >||||< q) a b c d e infixl 8 Source
(p >||||< q) a b c d e == (p a b c d, q e)
(p a b c d, q e) => (>||||<) k k k k k p q a b c d e |
class (p a b c d e, q f) => (p >|||||< q) a b c d e f infixl 8 Source
(p >|||||< q) a b c d e f == (p a b c d e, q f)
(p a b c d e, q f) => (>|||||<) k k k k k k p q a b c d e f |
class (p a b c d e f, q g) => (p >||||||< q) a b c d e f g infixl 8 Source
(p >||||||< q) a b c d e f g == (p a b c d e f, q g)
(p a b c d e f, q g) => (>||||||<) k k k k k k k p q a b c d e f g |
class (p a b c d e f g, q h) => (p >|||||||< q) a b c d e f g h infixl 8 Source
(p >|||||||< q) a b c d e f g h == (p a b c d e f g, q h)
(p a b c d e f g, q h) => (>|||||||<) k k k k k k k k p q a b c d e f g h |
class (p a b c d e f g h, q i) => (p >||||||||< q) a b c d e f g h i infixl 8 Source
(p >||||||||< q) a b c d e f g h i == (p a b c d e f g h, q i)
(p a b c d e f g h, q i) => (>||||||||<) k k k k k k k k k p q a b c d e f g h i |
class (p a b c d e f g h i, q j) => (p >|||||||||< q) a b c d e f g h i j infixl 8 Source
(p >||||||||< q) a b c d e f g h i j == (p a b c d e f g h i, q j)
(p a b c d e f g h i, q j) => (>|||||||||<) k k k k k k k k k k p q a b c d e f g h i j |
Irrefutable Combinators
, IR1
p
, ... and IR2
p
work almost like IR10
pp
itself,
but when used with In
or Has
,
In
or Has
gives up judging whether p
is satisfied
and believe that p
is satisfied.
They work a bit like irrefutable patterns in Haskell
and IR
stands for "IrRefutable".
They are useful when the constraint function p
receives a polymorphic argument
and the judgment depends on external contexts.
class p a b c d e f g => IR7 p a b c d e f g Source
p a b c d e f g => IR7 k k k k k k k p a b c d e f g |
class p a b c d e f g h => IR8 p a b c d e f g h Source
p a b c d e f g h => IR8 k k k k k k k k p a b c d e f g h |
class p a b c d e f g h i => IR9 p a b c d e f g h i Source
p a b c d e f g h i => IR9 k k k k k k k k k p a b c d e f g h i |
class p a b c d e f g h i j => IR10 p a b c d e f g h i j Source
p a b c d e f g h i j => IR10 k k k k k k k k k k p a b c d e f g h i j |
Helpers
Helpers for Identical Constructors
andI1 :: (forall b. Modify (a b) (In ts) p b => a b) -> AllOfI' ts as -> AllOfI' ts (Unary a p : as) infixr 0 Source
andI2 :: (forall b c. Modify2 (a b c) (In ts) p b c => a b c) -> AllOfI' ts as -> AllOfI' ts (Binary a p : as) infixr 0 Source
andI3 :: (forall b c d. Modify3 (a b c d) (In ts) p b c d => a b c d) -> AllOfI' ts as -> AllOfI' ts (Ternary a p : as) infixr 0 Source
andI4 :: (forall b c d e. Modify4 (a b c d e) (In ts) p b c d e => a b c d e) -> AllOfI' ts as -> AllOfI' ts (Quaternary a p : as) infixr 0 Source
andI5 :: (forall b c d e f. Modify5 (a b c d e f) (In ts) p b c d e f => a b c d e f) -> AllOfI' ts as -> AllOfI' ts (Quinary a p : as) infixr 0 Source
andI6 :: (forall b c d e f g. Modify6 (a b c d e f g) (In ts) p b c d e f g => a b c d e f g) -> AllOfI' ts as -> AllOfI' ts (Senary a p : as) infixr 0 Source
andI7 :: (forall b c d e f g h. Modify7 (a b c d e f g h) (In ts) p b c d e f g h => a b c d e f g h) -> AllOfI' ts as -> AllOfI' ts (Septenary a p : as) infixr 0 Source
andI8 :: (forall b c d e f g h i. Modify8 (a b c d e f g h i) (In ts) p b c d e f g h i => a b c d e f g h i) -> AllOfI' ts as -> AllOfI' ts (Octary a p : as) infixr 0 Source
andI9 :: (forall b c d e f g h i j. Modify9 (a b c d e f g h i j) (In ts) p b c d e f g h i j => a b c d e f g h i j) -> AllOfI' ts as -> AllOfI' ts (Nonary a p : as) infixr 0 Source
andI10 :: (forall b c d e f g h i j k. Modify10 (a b c d e f g h i j k) (In ts) p b c d e f g h i j k => a b c d e f g h i j k) -> AllOfI' ts as -> AllOfI' ts (Denary a p : as) infixr 0 Source
Helpers for Function Constructors
andF1 :: (forall b. Modify (a b) (In ts) p b => a b -> t) -> AllOfF' ts as t -> AllOfF' ts (Unary a p : as) t infixr 0 Source
andF2 :: (forall b c. Modify2 (a b c) (In ts) p b c => a b c -> t) -> AllOfF' ts as t -> AllOfF' ts (Binary a p : as) t infixr 0 Source
andF3 :: (forall b c d. Modify3 (a b c d) (In ts) p b c d => a b c d -> t) -> AllOfF' ts as t -> AllOfF' ts (Ternary a p : as) t infixr 0 Source
andF4 :: (forall b c d e. Modify4 (a b c d e) (In ts) p b c d e => a b c d e -> t) -> AllOfF' ts as t -> AllOfF' ts (Quaternary a p : as) t infixr 0 Source
andF5 :: (forall b c d e f. Modify5 (a b c d e f) (In ts) p b c d e f => a b c d e f -> t) -> AllOfF' ts as t -> AllOfF' ts (Quinary a p : as) t infixr 0 Source
andF6 :: (forall b c d e f g. Modify6 (a b c d e f g) (In ts) p b c d e f g => a b c d e f g -> t) -> AllOfF' ts as t -> AllOfF' ts (Senary a p : as) t infixr 0 Source
andF7 :: (forall b c d e f g h. Modify7 (a b c d e f g h) (In ts) p b c d e f g h => a b c d e f g h -> t) -> AllOfF' ts as t -> AllOfF' ts (Septenary a p : as) t infixr 0 Source
andF8 :: (forall b c d e f g h i. Modify8 (a b c d e f g h i) (In ts) p b c d e f g h i => a b c d e f g h i -> t) -> AllOfF' ts as t -> AllOfF' ts (Octary a p : as) t infixr 0 Source
andF9 :: (forall b c d e f g h i j. Modify9 (a b c d e f g h i j) (In ts) p b c d e f g h i j => a b c d e f g h i j -> t) -> AllOfF' ts as t -> AllOfF' ts (Nonary a p : as) t infixr 0 Source
andF10 :: (forall b c d e f g h i j k. Modify10 (a b c d e f g h i j k) (In ts) p b c d e f g h i j k => a b c d e f g h i j k -> t) -> AllOfF' ts as t -> AllOfF' ts (Denary a p : as) t infixr 0 Source
Examples
Example1: Hello
Let's begin with a basic example.
type Hellos = [ Type String, Type Int, Type Double, Unary [] Show, Quaternary (,,,) (This >|< This >||< This >|||< This)] hello :: In Hellos a => a -> String hello = projF ( (\s -> "hello, " ++ s) `andF` (\n -> "Mr. " ++ show n) `andF` (\x -> show (x / 2) ++ " times two") `andF` (\xs -> concatMap ((++", ") . show) xs ++ "period") `andF1` (\(x,y,z,w) -> hello x ++ " and " ++ hello y ++ " and " ++ hello z ++ " and " ++ hello w) `andF4` noneF :: AllOfF Hellos String) main = putStrLn $ hello ("world", 42 :: Int, 3.14 :: Double, [True, False])
This is the result.
hello, world and Mr. 42 and 1.57 times two and True, False, period
Example2: Printf
With a recursive cluss, you can easily make a function that can take a variable number of arguments. The function below is a simplified C-style printf.
type Printfs = [Binary (->) (Show >|< This), Type String] printf :: In Printfs a => String -> a printf s = projI ( (\x -> printf (go s (show x))) `andI2` s `andI` noneI :: AllOfI Printfs) where go ('@' : cs) t = t ++ cs go (c : cs) t = c : go cs t go [] _ = error "there is no '@' any more!" main = putStrLn $ printf "@ good @ and @" 12 "men" True
This is the result.
12 good "men" and True
Example3: Monad
Here is a more complex example. When the type of a "cluss method" is complex, you generally have to create newtypes (like Bind and Return below).
type Monads = [Type [], Unary (->) Pure, Unary (,) Monoid, Unary Wrap This] newtype Wrap m a = Wrap {unWrap :: m a} newtype Bind a b m = Bind {unBind :: m a -> (a -> m b) -> m b} newtype Return a m = Return {unReturn :: a -> m a} bind :: In Monads m => m a -> (a -> m b) -> m b bind = unBind $ proj ( Bind (\m k -> concatMap k m) `And` Bind (\m k e -> k (m e) e) `And1` Bind (\(a,x) k -> let (a2,x2) = k x in (a<>a2,x2)) `And1` Bind (\m k -> Wrap (unWrap m `bind` (unWrap . k))) `And1` None :: AllOf Monads (Bind a b)) return' :: In Monads m => a -> m a return' = unReturn $ proj ( Return (: []) `And` Return const `And1` Return ((,) mempty) `And1` Return (Wrap . return') `And1` None :: AllOf Monads (Return a)) infixl 1 `bind` main = print $ return' 1 `bind` replicate 3 `bind` (\n -> [n .. n+4])
This is the result.
[1,2,3,4,5,1,2,3,4,5,1,2,3,4,5]