Skip to content

Instantly share code, notes, and snippets.

@luqui
luqui / opaque.hs
Last active May 23, 2020 08:09
Natural transformations never need to type switch
{-# LANGUAGE RankNTypes, TypeApplications #-}
-- We give a constructive proof that any natural transformation that uses
-- a type switch in its implementation can also be implemented without the type switch,
-- as long as the domain functor is finitely Traversable (and the argument can easily
-- be modified to drop the finiteness property).
-- We do this by providing a function `opaquify` which takes an n.t. which may do
-- type switches, and returns an equivalent n.t. which does not.
@luqui
luqui / opaque.mkd
Created May 23, 2020 04:32
Natural transformations must treat their arguments opaquely

We will give some strong evidence for the claim "natural transformations must treat their arguments opauely". This is the best I can come up with short of defining a lambda calculus with type-switch and showing that the type-switch can always be eliminated (which I suspect would be possible) but is too difficult. Instead, we show that the requirement that a function be a natural transformation is invariant under encodings -- that is, if you mangle the argument in whatever way you like, and unmangle the result, you get the same thing as if you didn't do any mangling.

Therefore, in order to a natural transformation t :: F a -> G a to make an "exception" for a type, it would have to make the same exception for all possible encodings of that type as well. In particular, one possible encoding is to encode each incoming a in F as a unique integer. The resulting integers in the result G value show us exactly

@luqui
luqui / foldl.hs
Last active December 27, 2019 04:00
Example of how to get intermediate results from a Fold
import qualified Control.Foldl as Foldl
average :: Foldl.Fold Double Double
average = (/) <$> Foldl.sum <*> Foldl.genericLength
-- This could have been done more easily with the Foldl.scan function, but
-- I wanted to demonstrate how to access the intermediate states manually.
averages :: [Double] -> [Double]
averages xs
| Foldl.Fold step s0 obs <- average
@luqui
luqui / higher_products.hs
Last active September 11, 2018 15:28
Higher-kinded products using "axiomatic types"
{-# OPTIONS -fdefer-type-errors #-}
{-# LANGUAGE DataKinds, PolyKinds, TypeFamilies, TypeOperators, RankNTypes, GADTs, TypeApplications, ScopedTypeVariables, UndecidableInstances, MultiParamTypeClasses, TypeInType, TypeSynonymInstances, FlexibleInstances, InstanceSigs, FlexibleContexts #-}
import Prelude hiding (id, (.))
import Control.Category
import Data.Kind (Type)
import Unsafe.Coerce
import Data.Type.Equality
type family (~>) :: k -> k -> Type
-- In an alternate universe of Haskell where this worked...
data (Num a) => Complex a = a :+ a
instance Functor Complex where
fmap f (x :+ y) = f x :+ f y
instance Monad Complex where
return x = x :+ 0
join ((a :+ b) :+ (c :+ d)) = (a - d) :+ (b + c)
@luqui
luqui / baseball.html
Last active February 27, 2017 02:54
HTML help for Luke J
<!DOCTYPE html>
<html>
<head>
<style type="text/css">
h1 {
font-family:"Impact";
font-size: 48pt;
text-align: left;
text-indent: 48px;
color: #000;
@luqui
luqui / dragon.hs
Created December 16, 2016 16:50
dragon curve experiments
{-# LANGUAGE RankNTypes, GADTs, ConstraintKinds, ScopedTypeVariables, DeriveFunctor #-}
import Data.Monoid
import Data.Foldable (toList)
import Data.Constraint (Dict(..))
import qualified Data.DList as DList
import qualified Data.Sequence as Seq
class (Functor f) => DragonList f where
singleton :: a -> f a
@luqui
luqui / intervals.txt
Created November 28, 2013 06:39
An exploration of "small-ratio" musical intervals, compared to equal temperament.
An exploration of "small-ratio" musical intervals, compared to equal temperament. Each interval has
a perfect ratio before the colon, and a number of semitones with a cents (100th of a semitone) correction
approximation.
This is study for playing the Haken Continuum.
Root: 1 : 0
P2: 9/8 : 2 +3c
Fourth: 4/3 : 5 -2c
@luqui
luqui / gist:7611127
Created November 23, 2013 05:21
A neat list-like monoid that supports extracting information from both ends, even with undefined values in the middle.
{-# LANGUAGE RankNTypes #-}
import Data.Foldable
import Data.Monoid
newtype M a = M { getM :: forall m. Monoid m => (a -> m) -> m }
instance Monoid (M a) where
mempty = M $ const mempty
x `mappend` y = M $ \f -> getM x f `mappend` getM y f
{-# LANGUAGE ConstraintKinds, MultiParamTypeClasses, FunctionalDependencies #-}
class FromCon k a | a -> k where
convert :: k b => b -> a
instance FromCon Integral Integer where
convert = fromIntegral
foo :: Integer
foo = convert 4