Skip to content

Instantly share code, notes, and snippets.

@omnibs
Last active November 16, 2023 21:12
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 omnibs/5c2dc0162645854b0f3723170cbe89de to your computer and use it in GitHub Desktop.
Save omnibs/5c2dc0162645854b0f3723170cbe89de to your computer and use it in GitHub Desktop.
working example of "phantom constraint pattern"
#!/usr/bin/env nix-script-haskell
#!haskellPackages transformer
{-# LANGUAGE FlexibleInstances #-}
import B
import qualified Control.Monad.Reader as Reader
instance Reader a
instance State a
main :: IO ()
main = do
let initialGlobalEnv = Environment 123
Reader.runReaderT (runApp myApp) initialGlobalEnv
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
module B (Reader, State, Environment (..), runApp, myApp) where
import qualified Control.Monad.IO.Class as MonadIO
import qualified Control.Monad.Reader as Reader
import Prelude
class Reader r
class State s
askA :: Reader String => AppM String
askA = pure "hi"
getB :: State Int => AppM Int
getB = pure 1
putB :: State Int => Int -> AppM ()
putB _ = pure ()
-- Environment type
data Environment = Environment {someValue :: Int} -- mutable state, read-only values, etc. go in this record
newtype AppM a = UnsafeApp {runApp :: Reader.ReaderT Environment IO a} -- UnsafeApp not exported
deriving (Functor, Applicative, Monad, MonadIO.MonadIO, Reader.MonadReader Environment)
myApp :: (Reader String, State Int) => AppM ()
myApp = do
_ <- f
pure ()
f :: Reader String => AppM String
f = askA
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment