----------------------------------------------
-------------Haskell Language Notes-----------
-----------Because Aaron Vargo Said So--------
----------------------------------------------
Let's start with some math so we think we're
clear.
MATH VOCABULARY:
Starting from set theory we add the idea of a
(binary) Operation or op, o, over elements of
a set. We are going to build up toward
something like arithmetic with +, *, 1, 0 but
starting from fewer assumptions, defining some
different types of stuff as we get more
specific about our assumptions. Here are some
fun definitions:
Set: a collection S of elements e. S={e|e in
S}. Hahaha! You probably will add union,
intersection, complement, equality, the
empty set if you want to talk about more
than one Set in a single conversation. But
here we might not if our Set is a Universe
of discussion (i.e. it's closed, we can't
get out of it.)
Unary System: a set S with a unary operation
o(e) defined for each element in S, S might
be closed under o(), or not, leading
outside of S. But let's talk more about
closure after thinking about binary
operations.
Magma: a set S, with a Binary operation, o,
defined for each pair of elements in S, with
closure:
x,y in S => x o y is in S.
Naked Category/Semigroupoid/Semicategory/Pre-
category: A Magma where the Binary operation,
o, is Associative:
(f o g) o h = f o (g o h).
Category: a Precategory with an Identity element:
I in S s.t. I o x = x.
(Except that a category isn't necessarily
Closed. Wierd. See the Group-Like
Structures table at
https://en.wikipedia.org/wiki/Abelian_group
For a Category to have Associativity and not
have Closure? I don't think Associativity
is super meaningful unless you already have
closure. Otherwise what could (f o g) or (g
o h) mean such that that their result can
then be combined also using o? The results
have to be in the set, so that the second
operation can apply to them, because the
second operation only applies to things in
the set. But apparently the smart math folks
don't think that matters. Hmm. Sounds like
BS to me. But we continue.)
Monoid: a Closed Category:
x,y in S => x o y is in S, and
I o x = x.
Group: a Monoid with an Inverse:
x in S => inv(x) is in S. (-x,1/x...)
Abelian
Group: a Group with Commutativity:
x o y = y o x.
Ring: an Abelian Group with a second
operation that is associative,
distributive over the first, and with
an identity element "1". (Rng is a
Ring that lacks a 1).
Okay that was slightly interesting, slightly
fun, slightly weird. I mean, it's pretty
abstract but you can imagine maybe there are
things one might care about under each of
these definitions. Not sure yet. But for now
we can move towards our Holy Haskell
programming language by using a little bit of
that math.
HASKELL VOCABULARY
TYPE: Aaron seems to think a Type is just a
Set, more or less.
GROUP: a set S and associative operation o,
(making it also a PRECATEGORY),
including an identity element I in S
(making it also a CATEGORY),
with S closed under operation o
(making it also a MONOID),
with an inverse e' for each e in S
(making it also a GROUP).
E.g.:
Integers and + (with I=0, e'=-e).
Rationals and * (with I=1,e'=1/e).
{+-1,+-i} and * (with I=1,e'=1/e). Etc.
Angles and + (with I=0 degrees, e'=-e).
etc.
CATEGORY:
* should be, per the math, a SET, with a
BINARY OPERATION, which is ASSOCIATIVE,
that is CLOSED and has an IDENTITY element
under the operation.
* But in Haskell, a CATEGORY is: C0, CM,
COMP, that is:
* a set S=C0 (making it a SET, yes)
where C0 is a collection of Objects such
as A B C .. (each a TYPE in Haskell),
AND
* an operation o = CM
(making it a Unary System, yes),
where CM is a collection of MORPHISMS
from source to target Object (e.g.
f,g,.. where f: A->B, g: B->C etc.) AND
where CM is closed under composition
(no that would make it a MONOID!),
AND
* COMP, a concept of composition
of MORPHISMS, e.g.
f o g: A -> C (g first, then f),
* where Composition is ASSOCIATIVE
(f o g) o h = f o (g o h),
* AND CM contains the IDENTITY morphism
from each object to itself.
g:A->B implies g o idA = idB o g = g
* The difference being that in math a
category has one level of mappings called
the operation, whereas in Haskell it has
two levels one being called morphism and
the other being called composition.
2/8/23 Interestingly morphisms are unary and composition is
binary. A morphism is like a function, since functions take their
input and produce a single output. Some might use the concept of
an arrow, which goes from one thing to another (one other).
Whereas composition is some kind of weird binary operator, not for
doing stuff like addition or multiplication but for particularly
thinking about the operation of composing two functions together.
In a composite function the output of one is the input of the
other, considering each separately; but, composed, the input of
the first is the input of the composition and the output of the
second is the output of the composition, while the right thing
happens inside and you don't have to think about it. The
requirement of associativity of composition seems to be the main
trick here. It means you can somehow precompose a stack of
functions at the level of the function rather than by passing
their outputs up the stack. Like, if you knew what the internal
structure and variables were for two functions in a feeding
relationship, you could write a composed function that does both,
and of course that could be done by a compiler (and is), so maybe
this isn't so crazy after all.
HASK: a Haskell-category available in the
Haskell programming environment in which
C0 = Haskell types;
CM = Haskell functions;
. is the composition thereof, being
associative, closed, and having idT.
FUNCTOR:
Similarly as Categories relate objects to
objects via composable, associative
morphisms with closure and identity
Functors relate categories to categories
via mapping objects in one to objects in
the other, and
mapping morphisms in one to the other
(subject to mappings of source and
target objects) such that f:A>C
becomes F(f):F(A)>F(C)
Oh and let's have a little
Haskell Syntax:
"Is" or "is a" is a potential translation of a
bunch of different stuff in Haskell including
=> :: -> <- = == > : @. Let's be slightly
clearer:
=> ( A => B ) means "in the subsequent,
adjacent code, A must be that particular
subtype of As which is also a B".
a.k.a. Typeclass Restriction.
-> A -> B -> C is a function argument and
return value type declaration. It means
the function takes arguments of type A
followed by type B, and that the return
value of the function is of type C.
The way you know that -> precedes a
return value type is: it's the last one.
The other instances of -> separate
argument types. The reason one thing is
used for two meanings, well, then we get
to think we are more cool that way. It's
an in-group thing, you wouldn't
understand. (Thanks Haskellites, we love
you too!)
-> also has another meaning in defining
lambda operators.
-> has yet another meaning in the syntax
of case construction.
:: A :: B means B is a type and
A is of type B.
= A = B means define A to be B. That is, if
you see something that looks like A,
please substitute B, and that should get
you closer to where you want to go. Or
it means, A can be used as a name for B.
<- A <- B means assign the value of B (i.e.,
evaluate B to get its value and use that,
not the name B itself) to be the value of
the variable named A.
<- is also is a list comprehension
generator, sometimes.
== A == B means TRUE if A and B have the
same type and value, FALSE otherwise.
: A:B means a list where A is the first
value and B is the remainder of the list.
I.e. A is a list member, and B is a list.
For example if the list were actually
[A,b,c,d] then we could also write it as
A:[b,c,d]. "cons" in Lisp means the same
as :
@ A@B:C means you can use A to refer to the
whole list which has B at the head and C
as the remainder. Or, it means, You can
use B and C to refer to the head element
and the remaining list, of the list A. @
is pronounced "as".
>= A >= B means A is greater than or equal
to B, and has a boolean value.
<= A <= B means A is less than or equal to
B, and has a boolean value.
/= A /= B means A is not equal to B, and has
a boolean value.
>> Monad sequencing operator. A >> B means
run A, then run B.
>>= Monad sequencing operator with value
passing. A >>= B means run A, then jam
its output into B, and run B. I think.
(like unix pipe '|')
>@> Object composition operator.
TYPE CONSTRUCTOR: something that takes a type
and returns another type.
e.g. C: T>T
HIGHER ORDER FUNCTION: something that takes a
function and returns another function
e.g. D:F>F
TYPECLASSES provide polymorphism. Okay. See
=> above.
FIXED POINT:
a fixed point of a function f is a value a
such that f(a) == a. For example, 0 is a
fixed point of f(x)=x*3 because f(0)==0.
FUNCTIONAL:
Whatever.
MONAD:
a rather inscrutable mapping of mappings to
mappings with or without a mathematical
definition (no per wikipedia, yes per Aaron
Vargo), perhaps useful in composing
morphisms in categories or something. Like:
a TYPEDEF M { // define Monads with two ops
// wrap or monadify a value a.
UNIT(a) = { return M a; }
// unwrap a monadified value and use it.
BIND(f(M a)) = { return f(a); }
// Then f which supposedly handles a's
// can apply to monadified a, namely m(a),
// because the bind operation says how.
// This lets f seem to take monadified
// a's as arguments but only actually
// operate on a's.
}