Skip to content

Instantly share code, notes, and snippets.

@parsonsmatt
parsonsmatt / dont-use-hkd.md
Last active August 3, 2023 01:14
Another Failed HKD Attempt

Why not use HKD for the Esqueleto Records?

The most recent patch to esqueleto creates another datatype for esqueleto records: a Maybe variant, used when the table is introduced in a left join. This brings the record count up to three:

data Dog = Dog
    { name      :: String
    , age       :: Maybe Int
    , person    :: Maybe (Entity Person)
@parsonsmatt
parsonsmatt / MutDef.hs
Created November 29, 2022 19:02
How to redefine functions in Haskell, based on Hillel's article here: https://buttondown.email/hillelwayne/archive/i-am-disappointed-by-dynamic-typing/
{-# language BangPatterns #-}
module MutDef where
import Data.IORef
import System.IO.Unsafe
import Data.Map (Map)
import qualified Data.Map as Map
import GHC.Exts
@parsonsmatt
parsonsmatt / timestamp.hs
Created August 6, 2019 21:14
How long is your Template Haskell taking to run?
timestamp :: String -> Q a -> Q a
timestamp name action = do
start <- runIO getCurrentTime
runIO $ putStrLn $ "Starting " <> name <> ": " <> show start
a <- action
end <- runIO getCurrentTime
runIO $ do
putStrLn $ "Ending " <> name <> ": " <> show end
putStrLn $ "Elapased " <> name <> ": " <> show (diffUTCTime end start)
pure a
-- Dependency injection using a record-of-functions, but no ReaderT.
--
-- Download in an empty folder, then run with:
--
-- $ cabal install --lib --package-env . dep-t-0.4.4.0
-- $ runghc Main.hs
--
-- Some interesting aspects:
--
-- - No ReaderT transformer! Just plain functions (wrapped in helper datatypes).
{-# language OverloadedLists #-}
{-# OPTIONS_GHC -Wall #-}
module Overlays where
import Prelude hiding ((.))
import GHC.Stack
import Debug.Trace
liftType :: forall t. Typeable t => Q Type
liftType = do
let rep = typeRep @t
go rep
where
go :: forall (a :: k). TypeRep a -> Q Type
go tr =
case tr of
Con tyCon -> do
let
@parsonsmatt
parsonsmatt / no-thanks-acid-state.md
Created December 17, 2018 18:46
acid state antirecommendation

Someone asked whether or not acid-state was production ready. I shared my experiences:

parsonsmatt [11:32 AM] @nikolap it's used by cardano-wallet and Hackage. Based on my experience with acid-state, I'd say it is not a good choice for production data storage. For local desktop apps, SQLite is a much better choice, and for real production apps, Postgresql is king.

parsonsmatt [11:44 AM] acid-state did not have a test suite, at all, until I implemented the very first tests (for TemplateHaskell code generation) earlier this year. It has picked up some tests since then, but I'm still not confident in it's correctness.

It claims to be resilient to unplugging the power cord, but I doubt that, as it's not resilient to Ctrl-C: acid-state/acid-state#79

{-# language TypeApplications, FlexibleInstances, MultiParamTypeClasses, FlexibleContexts #-}
{-# language DataKinds, RankNTypes, PolyKinds, ScopedTypeVariables, GADTs, UndecidableInstances, TypeOperators #-}
{-# language ConstraintKinds #-}
module CatchR where
import Control.Monad.Reader
import Control.Monad.Except
to :: Reader (r, rest) a -> (r -> Reader rest a)
@parsonsmatt
parsonsmatt / gist:f64393b9349592b6f1c1
Last active August 28, 2020 17:36
class composition in ruby
# In Haskell, you write a function like this:
# f :: a -> b
# which reads as "f is a function from type a to b"
#
# Function composition allows you to chain functions together,
# building more powerful and complex composite functions from
# simpler component functions.
#
# OOP does not have a similar mechanism. Composition in OOP seems
# to mostly be limited to aggregation and delegation, neither of
@parsonsmatt
parsonsmatt / dbcomp.markdown
Created May 28, 2020 01:45
haskell database library comparison

there's kind of a ladder of complexity, where you have safety vs complexity vs how much to learn vs what the lib does for you. hasql and postgresql-simple have a 1 on safety and "what the lib does for you" but also have a 1 on complexity and how much to learn. if you know SQL, you can write raw string queries. But you also don't get any safety or migrations or composability. persistent is a 2 on the "how much to learn", and around a 3 on "how much it does for you." You get migrations, datatype definitions, very safe easy/common-case functions. The functions it gives you are perfectly safe, but you need to use esqueleto or raw SQL for fancy stuff so it's like 3 on safety. There's not a huge amount to learn, maybe it's a 2 here. esqueleto is a lot more powerful, but requires a lot more learning - so it's like a 4 on what it does for you and a 3 on how much to learn. It's not perfectly safe, but it does more safely than persistent, so it gets a 4. beam is complicated and difficult to learn. It has a 5 on how m