- Kiss type confusion goodbye as you learn to understand complex type signatures:
T[_[_, _], _]
,T[({type λ[A]=F[A, K]})#λ]
. - Level up your ability to write higher-order functions and define combinators to construct larger programs from smaller ones
- Learn how you can use rank-N types to program at a higher-level of abstraction, with strong correctness guarantees
- Discover how existentials help you compose functionality without exploding the size of type signatures
- Master type classes to generate generic, testable code without the tangling and non-local reasoning of inheritance
- Use "functional design patterns" like a boss, including functors, applicatives, monads, profunctors, monoids, and others
- Have your immutable cake and eat it too with "optics" that let you manipulate complex data structures with ease
- Traverse your own data structures without writing any recursive code through powerful, composable, generic recursion schemes
- Model effects with powerful, purely functional techniq
sealed trait Free[F[_], A] { self => | |
final def map[B](ab: A => B): Free[F, B] = Free.flatMap(self, ab andThen (Free.point[F, B](_))) | |
final def flatMap[B](afb: A => Free[F, B]): Free[F, B] = Free.flatMap(self, afb) | |
final def interpret[G[_]: Monad](fg: F ~> G): G[A] = self match { | |
case Free.Point(a0) => a0().point[G] | |
case Free.Effect(fa) => fg(fa) | |
case fm : Free.FlatMap[F, A] => | |
val ga0 = fm.fa.interpret[G](fg) | |
ga0.flatMap(a0 => fm.afb(a0).interpret[G](fg)) | |
} |
case class IO[A](unsafePerformIO: () => A) { | |
def map[B](ab: A => B): IO[B] = IO(() => ab(unsafePerformIO())) | |
def flatMap[B](afb: A => IO[B]): IO[B] =IO(() => afb(unsafePerformIO()).unsafePerformIO()) | |
def tryIO(ta: Throwable => A): IO[A] = | |
IO(() => IO.tryIO(unsafePerformIO()).unsafePerformIO() match { | |
case Left(t) => ta(t) | |
case Right(a) => a | |
}) | |
} | |
object IO { |
class Option<A> { | |
protected Option() { } | |
} | |
interface App<F, A> { | |
F proof(); | |
} | |
class OptionF { | |
private OptionF() {} | |
private static class AppOption<A> implements App<OptionF, A> { |
A type is a set of values. A value stores information at runtime in computer memory (such as a certain integer, a certain list of strings, etc.).
In many languages, functions are values (Haskell, PureScript, Javascript)! Or at least, you can pretend they are (Scala, Java).
These exercises were part of a LambdaConf Outpost meetup. You may find the instructions here.
-
Develop a model for boolean values (
Bool
), which may be either true or false.Think: Do you need an if-then-else construct? Why or why not?
Bonus: Develop a model for eithers (
Either
), whih can be one thing ("left") or another ("right"), and model a boolean as a partitioning of a set into two disjoint sets. -
Develop a model for optional values (
Maybe
/Option
), which are containers that are either empty ("nothing" / "none") or hold a single value ("just" / "some").
-
Develop a model for boolean values (
Bool
), which may be either true or false.Think: Do you need an if-then-else construct? Why or why not?
Bonus: Develop a model for eithers (
Either
), whih can be one thing ("left") or another ("right"), and model a boolean as a partitioning of a set into two disjoint sets.type Bool = forall a. a -> a -> a
_true :: Bool
module Main where | |
import Debug.Trace | |
import Halogen | |
main = do | |
trace "Hello sailor!" | |
module Halogen where | |
import Control.Monad.State.Trans | |
import Control.Monad.State.Class |
data Dep a b | |
dir :: forall a. String -> Dep a File | |
file :: forall a. String -> Dep a File | |
depends = git :// "git@github.com:bodil/purescript-signal.git" ## "1.2.3" <> | |
git :// "git@github.com:purescript-contrib/purescript-dom.git" ## "2.1.2" <> | |
bower :// "purescript-strongcheck" ## "0.7.1" |