mirror of
https://github.com/bitemyapp/learnhaskell.git
synced 2024-11-03 23:15:18 +00:00
Added epic tel/gclaramunt thread
This commit is contained in:
parent
6da4355a45
commit
d7f971d26d
@ -20,7 +20,7 @@ Cabal is equivalent to Ruby's Bundler, Python's pip, Node's NPM, Maven, etc. GHC
|
||||
|
||||
## Getting started
|
||||
|
||||
### For Ubuntu
|
||||
### Ubuntu
|
||||
|
||||
This PPA is excellent and is what I use on all my Linux dev and build machines: http://launchpad.net/~hvr/+archive/ghc
|
||||
|
||||
|
272
dialogues.md
272
dialogues.md
@ -661,3 +661,275 @@ variables
|
||||
22:46 < bitemyapp> based on the ranks/nesting
|
||||
22:46 < bitemyapp> / scope'ish
|
||||
```
|
||||
|
||||
## Epic Functor, algebra, Coyoneda discussion
|
||||
|
||||
* * * * *
|
||||
|
||||
bitemyapp edited 4 days ago | link | delete | reply
|
||||
|
||||
I realize this is partly because the examples are in Scala, but none
|
||||
of this gets at what a Functor really is.
|
||||
|
||||
Functor is an algebra.
|
||||
|
||||
Functor is an algebra with one operation, usually called map.
|
||||
|
||||
That one operation has a type something like:
|
||||
|
||||
```haskell
|
||||
(a -> b) -> f a -> f b
|
||||
```
|
||||
|
||||
That one operation should respect identity:
|
||||
|
||||
```
|
||||
map id = id
|
||||
```
|
||||
|
||||
And that one operation should be associative:
|
||||
|
||||
```
|
||||
map (p . q) = (map p) . (map q)
|
||||
```
|
||||
|
||||
That’s it people. That’s it. Functor is a very weak structure. Many
|
||||
things can be functor. Many of those things will not look anything
|
||||
like a “list”, “collection”, or even a “data structure”.
|
||||
|
||||
Understanding free objects, free versions of these algebraic
|
||||
structures, can lend a more faithful intuition for what these things
|
||||
are.
|
||||
|
||||
Glancing at Coyoneda (the free functor) should give one some idea of
|
||||
why you’re not dealing with something that has anything to do with
|
||||
lists.
|
||||
|
||||
Want to know more?
|
||||
|
||||
You know the drill: https://github.com/bitemyapp/learnhaskell
|
||||
|
||||
Edit:
|
||||
|
||||
Since I take great satisfaction in excising misunderstandings, I’m
|
||||
going to include a Functor instance that should help drop the
|
||||
“collections” oriented view of what they are.
|
||||
|
||||
```haskell
|
||||
-- (->) or -> is the type constructor for functions
|
||||
-- a -> a, the identity function's type is a type of
|
||||
-- -> taking two parameters of the same type (a and a)
|
||||
-- (->) a a analogous to Either a b
|
||||
instance Functor ((->) r) where
|
||||
map = (.)
|
||||
|
||||
-- (.) or . is function composition
|
||||
-- (.) :: (b -> c) -> (a -> b) -> a -> c
|
||||
-- more on this Functor instance:
|
||||
-- http://stackoverflow.com/questions/10294272/confused-about-function-as-instance-of-functor-in-haskell
|
||||
```
|
||||
|
||||
Bonus round for upvoting me:
|
||||
|
||||
http://www.haskellforall.com/2012/09/the-functor-design-pattern.html
|
||||
http://hackage.haskell.org/package/kan-extensions-3.7/docs/Data-Functor-Coyoneda.html
|
||||
http://oleksandrmanzyuk.wordpress.com/2013/01/18/co-yoneda-lemma/
|
||||
http://www.reddit.com/r/haskell/comments/17a33g/free_functors_the_reason_free_and_operational_are/c83p8k2
|
||||
https://gist.github.com/thoughtpolice/5843762
|
||||
|
||||
* * * * *
|
||||
|
||||
tel 4 days ago | link | reply
|
||||
|
||||
```
|
||||
Understanding free objects, free versions of these algebraic
|
||||
structures, can lend a more faithful intuition for what these things
|
||||
are.
|
||||
```
|
||||
|
||||
This is a super great point—it also, meaningfully, applies to other
|
||||
structures like Monads, Applicatives, or Monoids, Categories,
|
||||
Arrows. Really quickly, here’s Yoneda and Coyoneda (the “two” free
|
||||
functors)
|
||||
|
||||
```haskell
|
||||
newtype Yoneda f a = Yoenda { runYoneda :: forall b . (a -> b) -> f b }
|
||||
data Coyoneda f b where Coyoneda :: f a -> (a -> b) -> Coyoneda f b
|
||||
```
|
||||
|
||||
In each case we see that functor tends to mean having a parametric
|
||||
structure (the f) and a method of transforming the parameter to
|
||||
something else (the functions a -> b). When we “collapse” this free
|
||||
view of a functor we get to decide if, how, when, and why we combine
|
||||
that structure and its mapping function. For lists we, well, map
|
||||
it. For something like
|
||||
|
||||
```haskell
|
||||
data Liar a = Liar -- note that `a` does not appear on the right side
|
||||
```
|
||||
|
||||
we just throw the mapping function away.
|
||||
|
||||
(Another key point that’s a bit harder to see is that if you map the
|
||||
Yoneda/Coyoneda formulation repeatedly it does not store each and
|
||||
every mapping function but instead composes them all together and
|
||||
retains only that composition. This ensures that functors cannot “see”
|
||||
how many times fmap has been called. That would let you violate the
|
||||
functor laws!)
|
||||
|
||||
* * * * *
|
||||
|
||||
gclaramunt 3 days ago | link | reply
|
||||
|
||||
Do you have any reference of functor being an algebra? I’m intrigued
|
||||
|
||||
Since we’re clarifying what a functor is, I guess is worth noting that
|
||||
you’re talking about endofunctors in the (idealized) Hask category. In
|
||||
category theory, a functor is defined by two mappings: one for objects
|
||||
in the category and one for arrows, that must preserve identity and
|
||||
composition (the laws you mention). Since the mapping of objects is
|
||||
already given by the type constructor, here one needs to provide only
|
||||
the mapping of functions but it kind of irks me when ppl. say a
|
||||
functor is only defined by “map” :)
|
||||
|
||||
* * * * *
|
||||
|
||||
tel 2 days ago | link | reply
|
||||
|
||||
Functor is definitely an algebra. Its rules mean that it has tight
|
||||
relation to certain functors in CT.
|
||||
|
||||
* * * * *
|
||||
|
||||
gclaramunt edited 2 days ago | link | reply
|
||||
|
||||
Interesting… any refereces I can read? Or you’re talking about
|
||||
F-algebras?
|
||||
|
||||
* * * * *
|
||||
|
||||
tel 2 days ago | link | reply
|
||||
|
||||
I mean “algebra” as “set of operations and equalities”.
|
||||
|
||||
* * * * *
|
||||
|
||||
gclaramunt 2 days ago | link | reply
|
||||
|
||||
Ok. To be honest, I need to familiarize myself with the definition of
|
||||
algebra, is just that I had never heard this before :)
|
||||
|
||||
* * * * *
|
||||
|
||||
tel 1 day ago | link | reply
|
||||
|
||||
It’s an incredibly overloaded term, tbh. In the context of abstract
|
||||
algebra you’d probably want to think of a (G, L)-algebra as a set
|
||||
inductively defined by generators G and laws L. For instance, here’s a
|
||||
“free” monoid algebra (note that this isn’t a free monoid, but a “free
|
||||
monoid algebra” or a “free algebra of the monoid type” or a “(monoid,
|
||||
{})-algebra” maybe)
|
||||
|
||||
```haskell
|
||||
data FMonoid where
|
||||
Fmempty :: FMonoid
|
||||
Fmappend :: FMonoid -> FMonoid -> FMonoid
|
||||
|
||||
class Monoid FMonoid where -- this is wrong! doesn't follow laws!
|
||||
mempty = Fmempty
|
||||
mappend = Fmappend
|
||||
```
|
||||
|
||||
note that it has all the “generators” of the typeclass Monoid but
|
||||
follows none of the rules (mempty <> mempty != mempty). Typically we
|
||||
also want to add a set of constants to form the smallest free algebra
|
||||
over a set
|
||||
|
||||
```haskell
|
||||
data FMonoid a where
|
||||
Embed :: a -> FMonoid a
|
||||
Fmempty :: FMonoid a
|
||||
Fmappend :: FMonoid a -> FMonoid a -> FMonoid a
|
||||
```
|
||||
|
||||
* * * * *
|
||||
|
||||
gclaramunt 1 day ago | link | reply
|
||||
|
||||
Really interesting, thanks a lot! Now I’m trying to see how this ties
|
||||
to the Functor typeclass: G are the instance constructors and the
|
||||
functor laws make L ? I think I’m missing an important piece of the
|
||||
puzzle here :)
|
||||
|
||||
* * * * *
|
||||
|
||||
tel 1 day ago | link | reply
|
||||
|
||||
You’re not, that’s basically it.
|
||||
|
||||
```haskell
|
||||
data FFunctor f a where
|
||||
EmbedFunctor :: f a -> FFunctor f a
|
||||
Ffmap :: (a -> b) -> FFunctor f a -> FFunctor f b
|
||||
```
|
||||
|
||||
This lets you build the free (Functor, {})-algebra over some initial
|
||||
type f. If we translate it naively then it doesn’t follow the laws
|
||||
|
||||
```haskell
|
||||
class Functor (FFunctor f) where -- wrong!
|
||||
fmap = Ffmap
|
||||
```
|
||||
|
||||
but we can implement it properly if we’re a little more clever
|
||||
|
||||
```haskell
|
||||
class Functor (FFunctor f) where
|
||||
fmap f x = case x of
|
||||
EmbedFunctor fa -> Ffmap f x
|
||||
Ffmap g fa -> Ffmap (f . g) fa
|
||||
```
|
||||
|
||||
We need one more function, though, since we can’t use EmbedFunctor
|
||||
directly without exposing information about whether or not we’ve ever
|
||||
fmaped this functor (which shouldn’t be possible to access, that’s
|
||||
what fmap id = id says)
|
||||
|
||||
```haskell
|
||||
embed :: f a -> FFunctor f a
|
||||
embed fa = Ffmap id (EmbedFunctor fa)
|
||||
```
|
||||
|
||||
And now, if we think about it, we can see that every value of FFunctor
|
||||
constructed using embed and fmap is of the form
|
||||
|
||||
```haskell
|
||||
Ffmap fun (EmbedFunctor fa)
|
||||
```
|
||||
|
||||
And so that EmbedFunctor constructor is totally superfluous. Let’s
|
||||
remove it
|
||||
|
||||
```haskell
|
||||
data FFunctor f a where
|
||||
Ffmap :: (a -> b) -> f a -> FFunctor f b
|
||||
|
||||
embed :: f a -> FFunctor f a
|
||||
embed fa = Ffmap id fa
|
||||
```
|
||||
|
||||
And—well—this is just CoYoneda again!
|
||||
|
||||
```haskell
|
||||
lower :: Functor f => FFunctor f a -> f a
|
||||
lower (Ffmap f fa) = fmap f fa
|
||||
```
|
||||
|
||||
* * * * *
|
||||
|
||||
gclaramunt about 9 hours ago | link | reply
|
||||
|
||||
Nice Haven’t digested it properly but I see the trick is to capture
|
||||
the functor with a datatype (is the same thing with free monads,
|
||||
right?) Now is easier to see from where CoYoneda comes, thanks! (you
|
||||
did show me an important piece of the puzzle :P )
|
||||
|
Loading…
Reference in New Issue
Block a user