module TypeClass class Monad (m : U → U) where bind : ∀ a b. m a → (a → m b) → m b pure : ∀ a. a → m a infixl 1 _>>=_ _>>_ _>>=_ : {0 m} {{Monad m}} {0 a b} -> (m a) -> (a -> m b) -> m b ma >>= amb = bind ma amb _>>_ : ∀ m a b. {{Monad m}} -> m a -> m b -> m b ma >> mb = mb data Either : U -> U -> U where Left : ∀ A B. A -> Either A B Right : ∀ A B. B -> Either A B instance {a} -> Monad (Either a) where bind (Left a) amb = Left a bind (Right b) amb = amb b pure a = Right a data Maybe : U -> U where Just : ∀ A. A -> Maybe A Nothing : ∀ A. Maybe A instance Monad Maybe where bind Nothing amb = Nothing bind (Just a) amb = amb a pure a = Just a infixr 7 _::_ data List : U -> U where Nil : ∀ A. List A _::_ : ∀ A. A -> List A -> List A infixl 7 _++_ _++_ : ∀ A. List A -> List A -> List A Nil ++ ys = ys (x :: xs) ++ ys = x :: (xs ++ ys) instance Monad List where bind Nil f = Nil bind (x :: xs) f = f x ++ bind xs f pure x = x :: Nil infixr 1 _,_ data Pair : U -> U -> U where _,_ : ∀ A B. A -> B -> Pair A B ptype Int test : Maybe Int test = pure 10 foo : Int -> Maybe Int foo x = Just 42 >> Just x >>= (\ x => pure 10) bar : Int -> Maybe Int bar x = do let y = x z <- Just x pure z baz : ∀ A B. List A -> List B -> List (Pair A B) baz xs ys = do x <- xs y <- ys pure (x , y)