packages feed

kindly-functors-0.1.0.0: test/Main.hs

{-# LANGUAGE ImportQualifiedPost #-}
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE InstanceSigs #-}

module Main (main) where

--------------------------------------------------------------------------------

import Data.Functor.Contravariant (Op (..), Predicate (..))
import Data.Functor.Identity (Identity (..))
import Kindly qualified as UUT
import Test.Hspec (describe, hspec, it, shouldBe)
import Data.Maybe (maybeToList)
import Data.Functor.Classes (Show1, Eq1)

--------------------------------------------------------------------------------

main :: IO ()
main = hspec $ do
  describe "fmap" $ do
    it "works covariantly" $ do
      UUT.fmap show (Identity True) `shouldBe` Identity "True"
    it "works contravariantly" $ do
      getPredicate (UUT.fmap (Op read) (Predicate not)) "True" `shouldBe` False
    it "composes" $ do
      (UUT.fmap . UUT.fmap) show (Just (Just True)) `shouldBe` Just (Just "True")
      UUT.fmap ((\f -> f "True") . getPredicate) ((UUT.fmap . UUT.fmap) (Op read) (Just (Predicate not))) `shouldBe` Just False

  describe "lmap" $ do
    it "works covariantly" $ do
      UUT.lmap show (True, False) `shouldBe` ("True", False)
    it "works contravariantly" $ do
      UUT.lmap (Op read) not "True" `shouldBe` False

  describe "rmap" $ do
    it "works covariantly" $ do
      UUT.rmap show (True, False) `shouldBe` (True, "False")

  describe "bimap" $ do
    it "works covariantly" $ do
      UUT.bimap show (read @()) (Left True) `shouldBe` Left "True"
      UUT.bimap (read @Int) show ("1", True) `shouldBe` (1, "True")
    it "works contravariantly" $ do
      UUT.bimap (Op (read @Int)) show (+ 1) "0" `shouldBe` "1"

  describe "bimap" $ do
    it "works covariantly" $ do
      UUT.trimap show show show (True, False, ()) `shouldBe` ("True", "False", "()")


  describe "bmap" $ do
    it "works" $ do
      let hkd = MyHKD (Just True) Nothing
      UUT.bmap maybeToList hkd `shouldBe` MyHKD [True] []


data MyHKD f = MyHKD {one :: f Bool, two :: f ()}

instance Show1 f => Show (MyHKD f) where
  show MyHKD {..} = "MyHKD {one = " <> show one <> ", two = " <> show two <> "}"

instance Eq1 f => Eq (MyHKD f) where
  (MyHKD a b) == (MyHKD a' b') = a == a' && b == b'  

instance UUT.CategoricalFunctor MyHKD where
  type Dom MyHKD = (->) UUT.~> (->)
  type Cod MyHKD = (->)

  map :: (UUT.Nat (->) (->)) f g -> MyHKD f -> MyHKD g
  map (UUT.Nat nat) MyHKD {..} = MyHKD (nat one) (nat two)

newtype MyHKD2 p = MyHKD2 {field :: p () Bool}

instance UUT.CategoricalFunctor MyHKD2 where
  type Dom MyHKD2 = (->) UUT.~> ((->) UUT.~> (->))
  type Cod MyHKD2 = (->)

  map :: UUT.Dom MyHKD2 p q -> MyHKD2 p -> MyHKD2 q
  map (UUT.Nat (UUT.Nat nat)) MyHKD2 {..} = MyHKD2 (nat field)