Skip to content

Instantly share code, notes, and snippets.

View robrix's full-sized avatar
🌊
every dot and stroke I paint will be alive

Rob Rix robrix

🌊
every dot and stroke I paint will be alive
View GitHub Profile
@robrix
robrix / Ref.hs
Created July 23, 2022 14:20
Ref effect, bridged to State
data Ref ref (m :: K.Type -> K.Type) k where
NewRef :: a -> Ref ref m (ref a)
ReadRef :: ref a -> Ref ref m a
WriteRef :: ref a -> a -> Ref ref m ()
newRef :: Has (Ref ref) sig m => a -> m (ref a)
newRef a = send (NewRef a)
readRef :: Has (Ref ref) sig m => ref a -> m a
readRef ref = send (ReadRef ref)
@robrix
robrix / Failover.hs
Last active June 26, 2022 12:27
A Failover effect, like Choose but with laws like Maybe's Alternative instance
import Control.Algebra
-- Failover effect
failover :: Has Failover sig m => m a -> m a -> m a
failover a b = send (Failover a b)
infixl 3 `failover`
data Failover m k where
@robrix
robrix / MonadicFolds.hs
Created April 2, 2022 20:05
Monadic cata, ana, and hylo
newtype Fix f = In { out :: f (Fix f) }
cata :: Functor f => (f a -> a) -> (Fix f -> a)
cata alg = go where go = alg . fmap go . out
ana :: Functor f => (a -> f a) -> (a -> Fix f)
ana coalg = go where go = In . fmap go . coalg
hylo1 :: Functor f => (f b -> b) -> (a -> f a) -> (a -> b)
@robrix
robrix / LC.hs
Created July 17, 2021 15:35
A catamorphism-based interpreter and an abstract machine for the untyped lambda calculus
type Name = String
-- first-order syntax
data Tm
= Var Name
| Abs Name Tm
| App Tm Tm
deriving (Eq, Ord, Show)
type Env = [(Name, Val)]
@robrix
robrix / MuNu.hs
Created June 20, 2021 23:19
Least and greatest fixed-points in Haskell
newtype Mu f = Mu (forall r . (f r -> r) -> r)
foldMu :: (f a -> a) -> Mu f -> a
foldMu alg (Mu f) = f alg
unfoldMu :: Functor f => (a -> f a) -> a -> Mu f
unfoldMu coalg a = Mu $ \ alg -> refold alg coalg a
refoldMu :: Functor f => (f b -> b) -> (a -> f a) -> a -> b
refoldMu f g = foldMu f . unfoldMu g
@robrix
robrix / FoldsAndUnfolds.hs
Created March 31, 2021 22:44
Recursion schemes over lists, in contrast with foldr/unfoldr
module FoldsAndUnfolds where
import Data.List -- for unfoldr
class Functor f => Recursive f t | t -> f where
project :: t -> f t
cata :: (f a -> a) -> t -> a
cata alg = go where go = alg . fmap go . project
@robrix
robrix / Optics.hs
Created October 9, 2020 15:05
Optics via fused-effects
{-# LANGUAGE RankNTypes #-}
module Optics where
import Control.Category ((>>>))
import qualified Control.Category as Cat
import Control.Effect.Empty
import Control.Effect.NonDet hiding (empty)
import Control.Monad ((<=<))
-- riffing off of @serras’s post https://gist.github.com/serras/5152ec18ec5223b676cc67cac0e99b70
@robrix
robrix / Selective2.hs
Created October 3, 2020 19:30
What do we gain and what do we break by distributing f over -> in Selective?
class Applicative f => Selective f where
branch :: f (Either a b) -> f (a -> c) -> f (b -> c) -> f c
branch ab f g = fmap (fmap Left) ab `select` fmap (fmap Right) f `select` g
select :: f (Either a b) -> f (a -> b) -> f b
select ab f = branch ab f (pure id)
{-# MINIMAL branch | select #-} -- Defining in terms of both to double-check my work
filteredBy :: (Alternative f, Selective f) => f a -> (a -> Bool) -> f a -- from Staged Selective Parser Combinators
@robrix
robrix / Deriving.hs
Last active September 28, 2020 15:28
Deriving of Functor instances via Applicative, and Functor & Applicative instances via Monad, using DerivingVia
module Deriving
( ApplicativeInstance(..)
, MonadInstance(..)
) where
import Control.Applicative (liftA, liftA2)
import Control.Monad (ap, liftM, liftM2)
-- | 'Functor' instances derivable via an 'Applicative' instance, for use with @-XDerivingVia@.
--
@robrix
robrix / Mendler.hs
Created September 3, 2020 15:02
Mendler-style iteration in Haskell
{-# LANGUAGE FunctionalDependencies #-}
{-# LANGUAGE RankNTypes #-}
module Mendler where
class Iter b t | t -> b where
iter :: (forall x . (x -> a) -> b x -> a) -> t -> a
data ListF a b = Nil | Cons a b
instance Iter (ListF a) [a] where