Skip to content

Instantly share code, notes, and snippets.

@smunix
Last active April 9, 2021 10:24
Show Gist options
  • Save smunix/235bfe61b821fdf831140c0ec32fc5c3 to your computer and use it in GitHub Desktop.
Save smunix/235bfe61b821fdf831140c0ec32fc5c3 to your computer and use it in GitHub Desktop.
Playing with endomorphisms and monoids
newtype Fn a = Fn {unFn :: a -> a}
instance Semigroup (Fn a) where
(<>) (Fn a) (Fn b) = Fn (b . a)
import Control.Monad
import Data.Foldable (fold)
import Data.Monoid (appEndo)
import Hedgehog
instance Monoid (Fn a) where
mempty = Fn id
instance (Num a) => Num (Fn a) where
(+) = (<>)
fromInteger 0 = Fn id
fromInteger x = Fn (fromIntegral x *)
fldr :: Foldable t => (a -> b -> b) -> b -> t a -> b
fldr op i as = unFn (foldMap (Fn . op) as) i
semigroupFnChecks :: IO Bool
semigroupFnChecks =
checkParallel $
Group
"SemiGroup"
[ ( "merging",
property do
unFn (2 + 3) 1 === 6
unFn (3 + 2 + 3) 1 === 18
),
( "foldr <-> foldMap",
property do
fldr (+) 0 [1 .. 10] === 55
unFn (foldMap id [1, 2, 4, 6, 8, 10]) 1 === 3840
unFn (fold [1, 2, 4, 6, 8, 10]) 1 === 3840
)
]
@smunix
Copy link
Author

smunix commented Apr 9, 2021

Strictly speaking, there's a data type Endo defined in Data.Monoid that does exactly what our Fn type here does

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment