module Fp071 where
import Control.Monad.Instances

data Tree a = Leaf a | Branch (Tree a) a (Tree a) 
  deriving Show

instance Functor Tree where
--fmap :: (a -> b) -> Tree a -> Tree b
  fmap g (Leaf x)       = Leaf (g x)
  fmap g (Branch l x r) = Branch (fmap g l) (g x) (fmap g r)


class Functor f => Pointed f where
  pure :: a -> f a -- aka singleton, return, unit, point

instance Pointed Maybe where
--pure :: a -> Maybe a
  pure x  = Just x

instance Pointed [] where
--pure :: a -> [a]
  pure x  = [x]

instance Pointed ((->) r) where
--pure :: a -> r -> a
  pure = const

-- не очень-то хорошо, контекст Monoid e => может спасти дело 
instance Pointed ((,) e) where
--pure :: a -> (e,a)
  pure x = (undefined, x)

instance Pointed (Either l) where
--pure :: a -> Either l a
  pure y = Right y

instance Pointed Tree where
--pure :: a -> Tree a
  pure x = Leaf x -- как для деревьев другой структуры, например с Nil?
