{-# 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)