demo_applicative = do
  print $ (pure id <*> ZipList [1])
  let x :: (Num a) => ZipList a
      x = pure 1
   in print ((pure (\ x -> 2 * x)) <*> x)

  print (ZipList [\ x -> 2*x, \ x -> 3*x] <*> pure 1)
  print (pure ($ 1) <*> ZipList [\ x -> 2*x, \ x -> 3*x])

  -- (+) <$> [1] creates partial function in `f` domain
--  then, this function is applied with [2]
  print (pure (+) <*> [1] <*> [2])
  print ((+) <$> [1] <*> [2])
demo_applicative = do
  print $ (pure id <*> ZipList [1])
  let x :: (Num a) => ZipList a
      x = pure 1
   in print ((pure (\ x -> 2 * x)) <*> x)

  print (ZipList [\ x -> 2*x, \ x -> 3*x] <*> pure 1)
  print (pure ($ 1) <*> ZipList [\ x -> 2*x, \ x -> 3*x])

  -- (+) <$> [1] creates partial function in `f` domain
--  then, this function is applied with [2]
  print (pure (+) <*> [1] <*> [2])
  print ((+) <$> [1] <*> [2])
demo_applicative = do
  print $ (pure id <*> ZipList [1])
  let x :: (Num a) => ZipList a
      x = pure 1
   in print ((pure (\ x -> 2 * x)) <*> x)

  print (ZipList [\ x -> 2*x, \ x -> 3*x] <*> pure 1)
  print (pure ($ 1) <*> ZipList [\ x -> 2*x, \ x -> 3*x])

  -- (+) <$> [1] creates partial function in `f` domain
--  then, this function is applied with [2]
  print (pure (+) <*> [1] <*> [2])
  print ((+) <$> [1] <*> [2])