Skip to content

Instantly share code, notes, and snippets.

@edsko
Created June 20, 2018 06:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save edsko/7733568361ccd2ba8f1325125bd7f177 to your computer and use it in GitHub Desktop.
Save edsko/7733568361ccd2ba8f1325125bd7f177 to your computer and use it in GitHub Desktop.
module Blog where
import Prelude hiding ((.), id)
import Control.Category
import Data.Bifunctor
{-------------------------------------------------------------------------------
Fixed points
-------------------------------------------------------------------------------}
fix :: (a -> a) -> a
fix f = let a = fix f in f a
fac :: (Int -> Int) -> Int -> Int
fac r 1 = 1
fac r n = n * r (n - 1)
skim :: (Int -> Int) -> Int -> Int
skim r 1 = 1
skim r n = (fac r n) - 1
skimSpec :: Int -> Int
skimSpec 1 = 1
skimSpec n = n * skimSpec (n - 1) - 1
{-------------------------------------------------------------------------------
Inheritance
-------------------------------------------------------------------------------}
{-
data Counter = Counter {
tick :: Counter
, display :: Int
}
mkCounter :: (Int -> Counter) -> (Int -> Counter)
mkCounter self n = Counter {
tick = self (n + 1)
, display = n
}
twice :: (Int -> Counter) -> (Int -> Counter)
twice self n = (mkCounter self n) {
display = n * 2
}
-}
{-------------------------------------------------------------------------------
Lenses
-------------------------------------------------------------------------------}
data Lens a b = Lens {
get :: a -> b
, modify :: (b -> b) -> (a -> a)
}
instance Category Lens where
id = Lens id id
l . l' = Lens (get l . get l') (modify l' . modify l)
_1 :: Lens (a, b) a
_1 = Lens fst first
_2 :: Lens (a, b) b
_2 = Lens snd second
{-------------------------------------------------------------------------------
Extending state
-------------------------------------------------------------------------------}
data Counter = Counter {
tick :: Counter
, tock :: Counter
, display :: String
}
mkCounter' :: (Int -> Counter) -> (Int -> Counter)
mkCounter' self n = Counter {
tick = self (n + 1)
, tock = self (n + 1)
, display = show n
}
-- ticktock' :: ((Int, Int) -> Counter) -> (Int, Int) -> Counter
-- ticktock' self (n, m) = mkCounter' (self . _) n
mkCounter :: Lens st Int -> (st -> Counter) -> (st -> Counter)
mkCounter l self st = Counter {
tick = self (modify l (+ 1) st)
, tock = self (modify l (+ 1) st)
, display = show (get l st)
}
ticktock :: Lens st (Int, Int) -> (st -> Counter) -> (st -> Counter)
ticktock l self st = (mkCounter (_1 . l) self st) {
tock = self (modify (_2 . l) (+ 1) st)
, display = show (get l st)
}
{-
data Counter = Counter {
tick :: Counter
, display :: Int
}
mkCounter :: Int -> Counter
mkCounter n = Counter {
tick = mkCounter (n + 1)
, display = n
}
twice :: Int -> Counter
twice n = (mkCounter n) {
display = n * 2
}
-}
{-------------------------------------------------------------------------------
Tests
-------------------------------------------------------------------------------}
main :: IO ()
main = do
print $ fix fac 5
print $ fix skim 5
print $ skimSpec 5
putStrLn $ display (tick (tock (tick (fix (ticktock id) (0, 0)))))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment