In this article, I'll explain why implementing numbers with just algebraic datatypes is desirable. I'll then talk about common implementations of FFT (Fast Fourier Transform) and why they hide inherent inefficiencies. I'll then show how to implement integers and complex numbers with just algebraic datatypes, in a way that is extremely simple and elegant. I'll conclude by deriving a pure functional implementation of complex FFT with just datatypes, no floats.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
data Complex = C Double Double deriving Show | |
data Nat = E | O Nat | I Nat deriving Show | |
data Tree a = L a | B (Tree a) (Tree a) deriving Show | |
cScale :: Double -> Complex -> Complex | |
cScale s (C ar ai) = C (ar * s) (ai * s) | |
cAdd :: Complex -> Complex -> Complex | |
cAdd (C ar ai) (C br bi) = C (ar + br) (ai + bi) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
let | |
nixpkgs = builtins.fetchTarball { | |
url = "https://github.com/NixOS/nixpkgs/archive/c473cc8714710179df205b153f4e9fa007107ff9.tar.gz"; | |
sha256 = "0q7rnlp1djxc9ikj89c0ifzihl4wfvri3q1bvi75d2wrz844b4lq"; | |
}; | |
compiler = "ghc921"; | |
overlay = pkgsNew: pkgsOld: { | |
ghcid = pkgsNew.haskell.packages."${compiler}".ghcid; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE GADTs #-} | |
import Data.Monoid | |
import System.Environment | |
data Coyoneda f a where | |
Coyoneda :: (b -> a) -> f b -> Coyoneda f a | |
instance Functor (Coyoneda f) where | |
fmap f (Coyoneda b2a fb) = Coyoneda (f . b2a) fb |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
{-# LANGUAGE DeriveGeneric #-} | |
{-# LANGUAGE TypeFamilies #-} | |
{-# LANGUAGE TypeOperators #-} | |
{-# LANGUAGE DataKinds #-} | |
import Data.Aeson (ToJSON) | |
import Data.ByteString (ByteString) | |
import Data.Map (Map, fromList) | |
import Data.Monoid ((<>)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-- Attempt splitting an 'App Renderer' into smaller renderers using the Contravariant Divisible class; | |
-- Didn't really work out great, seems better to just use simple contramaps to map each renderer into | |
-- a `Renderer AppState` and then use a monoid to fold them. | |
{-# language InstanceSigs #-} | |
module Main where | |
import Data.Foldable | |
import Data.Functor.Contravariant | |
import Data.Functor.Contravariant.Divisible |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE DataKinds #-} | |
{-# LANGUAGE FlexibleInstances #-} | |
{-# LANGUAGE GeneralizedNewtypeDeriving #-} | |
{-# LANGUAGE KindSignatures #-} | |
{-# LANGUAGE LambdaCase #-} | |
{-# LANGUAGE MultiParamTypeClasses #-} | |
{-# LANGUAGE OverloadedStrings #-} | |
{-# LANGUAGE ScopedTypeVariables #-} | |
{-# LANGUAGE TypeOperators #-} | |
{-# LANGUAGE TypeFamilies #-} |
Run from ghci
. Must have attoparsec
available via cabal repl
.
:set -XOverloadedStrings
import Prelude
import Control.Applicative
import Data.Attoparsec.Text
data IPAddress = IPAddress Int Int Int Int deriving (Eq, Show)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
module Main where | |
import System.Environment | |
import Data.Monoid | |
import Control.Monad | |
import Data.Aeson | |
import qualified Data.Text as T | |
import qualified Data.Text.IO as T | |
import Network.HTTP.Client |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{-# LANGUAGE OverloadedStrings #-} | |
module CommandParser where | |
import Data.Attoparsec.Char8 | |
import Control.Applicative | |
import qualified Data.Text.Lazy as L | |
import Data.Text.Encoding | |
data Command = Retrieve | Delete | New deriving Show |
NewerOlder