{-# LANGUAGE ImportQualifiedPost #-} {-# LANGUAGE InstanceSigs #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TypeApplications #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} module Main (main) where -------------------------------------------------------------------------------- import Data.Functor.Contravariant (Op (..), Predicate (..)) import Data.Functor.Identity (Identity (..)) import Data.Maybe (maybeToList) import Kindly qualified as UUT import Test.Hspec (describe, hspec, it, shouldBe) -------------------------------------------------------------------------------- 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 project (UUT.bmap maybeToList hkd) `shouldBe` ([True], []) data MyHKD f = MyHKD {one :: f Bool, two :: f ()} project :: MyHKD f -> (f Bool, f ()) project MyHKD {..} = (one, two) 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)