Haskell is the toughest thing I've set out to learn so far. Haskell from First Principles has done a great job of building up my understanding a piece at a time. The author breaks down the complexity and instills comprehension without hand waving metaphors, so you earn a good intuitive grasp backed up by a solid understanding of the actual logic. By the time he says "a monad is an applicative functor ..." you are fully prepared to know exactly what that means in terms of the functions available and the programmatic laws they follow.
It's good stuff. I'm about 2/3 of the way through.
There's a bit where you have to implement law-abiding instances of the major typeclasses that build up the infamous monad. I'm recording a template of the way those tests are constructed. When it gets time to write real code, tests will need to be broken out of the main library, but that's the easy part. I'll want this for my notes.
module TypeCheckingExample where -- Imports for testing only import Test.QuickCheck import Test.QuickCheck.Checkers import Test.QuickCheck.Classes -- Data Constructor data Demo a = Demo a deriving (Eq, Show) -- TypeClass instances instance (Monoid a) => Monoid (Demo a) where mempty = undefined mappend = undefined instance Functor Demo where fmap = undefined instance Applicative Demo where pure = undefined (<*>) = undefined instance Monad Demo where return = undefined (>>=) = undefined -- Testing Section -- Testing for associativity requires a three-tuple of types for which -- 'arbitratry' can produce functions type Associatable = (Integer, Char, String) -- Typeclass instances required for QuickCheck instance (Arbitrary a) => Arbitrary (Demo a) where arbitrary = undefined instance Eq a => EqProp (Demo a) where (=-=) = eq -- main main :: IO () main = do quickBatch $ monoid (undefined :: Demo [Integer]) quickBatch $ functor (undefined :: Demo Associatable) quickBatch $ applicative (undefined :: Demo Associatable) quickBatch $ monad (undefined :: Demo Associatable)