---------------------------------------------- -------------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. }