Welcome! Got a question? Do you have -Ypartial-unification turned on? Other FAQs: http://typelevel.org/cats/faq.html
trait Functor[F[+_]]
cats-mtl
if it works out, you know what I think :)
MonadLayerControl
, when they don’t even need it at all, and should only use ApplicativeAsk
, MonadState
et al
IO
requires some subtlety when teaching it, so you might want to make sure they know how to write code with algebras first
State
without using s => (a, s)
, but only the combinators
IO
as an opaque entity imho
List
behaves weirdly?
*>
means "and then"
State
, checkIO
, check
Ok the intuition holds...
List(1,2,3) *> List(4, 5, 6)
<--- intuition breaks
fs2.Stream
behaves like List
in many respects so this is a good exercise regardless
StateT
-type solution
Most literature focuses on implementing them on one hand, or in "real world examples" without much explanations on the other, whereas I think developing the sort of thinking that lets you write code using algebras only is very important, and not necessarily always explained well
@felher this really matters to me so I want to expand a bit. Let's take State
as an example. In most cases books/tutorial fall in two categories:
modify
function that we can use in a for comprehension. Don't worry about how it works now...[proceeds with concrete example]
"a => (a, s)
where each function gets a new copy of the State. If we write down a couple of example we can see that it fits the Monad abstraction. Let's write the instance for Monad"Obviously they are both useful in different respects, however there are drawbacks:
IO
.I like to use a third approach. After having explained what the main algebras bring to the table (Functor lifts 1-arg functions, Applicative lifts n-ary functions, Monad gives you context sensitivity), I present State like this:
State is a datatype representing computations that describe modifications to a value, with the following algebra:
trait State[S, A] // S state, A output
object State {
def get[S]: State[S, S]
def set[S](s: S): State[S, Unit]
implicit def m: Monad[State[S, ?]] // stress that this implies Functor and Applicative
}
and then you have them write programs in this "language", without knowing anything about the internal representation, but only the State algebra (get, set, what the type means, any laws, the monad instance). After they manage to use it like that, you can explain how it's implemented (typically you'll go back and forth a few times in real life). The advantage is that this is aimed to instill the sort of algebraic thinking that is not only one of the biggest advantages of FP, but also necessary when you deal with opaque/complex abstractions like IO
or Stream