Skip to content

Instantly share code, notes, and snippets.

@rewinfrey
Created July 12, 2017 07:10
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 rewinfrey/261aceacd47d5e3e42ffcb31d3965935 to your computer and use it in GitHub Desktop.
Save rewinfrey/261aceacd47d5e3e42ffcb31d3965935 to your computer and use it in GitHub Desktop.
What do you do when you have a Thing but no db id?
#!/usr/bin/env stack
-- stack script --resolver lts-8.12
{-# LANGUAGE OverloadedStrings #-}
import Data.Text
import System.Random
data Thing = Thing { id :: Int, name :: Text } deriving Show
main :: IO ()
main = do
let thing1 = flip Thing "Pauly Shore"
let thing2 = flip Thing "Terry Kiser"
print =<< save thing1
print =<< save thing2
let thing1' = Thing' "Jason Silverman"
let thing2' = Thing' "Jason Bateman"
print =<< save' thing1'
print =<< save' thing2'
{-
Since all things in Haskell are functions (big stretch here), we can represent our Thing without
an id as a partially applied function. Not useful, but including it to illustrate the problem.
Type aliases can be useful in this context because we can give our partially applied function
a type. Unfortunately this limits access to the data inside the UnsavedThing, making this approach
problematic for anything practical (like saving that data in the db).
-}
type UnsavedThing = (Int -> Thing)
save :: UnsavedThing -> IO Thing
save unsavedThing = do
id' <- saveOperation unsavedThing
pure $ unsavedThing id'
-- Problem: How can I extract the data to save from a partially applied function?
where saveOperation unsavedThing = randomIO
{-
To work around this, you could construct pairs of ids and Things and use a convenience Type alias.
This is a zero abstraction approximation of what Persistent is doing but without the overhead of TemplateHaskell.
-}
data Thing' = Thing' { name' :: Text } deriving Show
type IdThing' = (Int, Thing')
save' :: Thing' -> IO IdThing'
save' thing = do
id' <- saveOperation thing
pure (id', thing)
where saveOperation thing = const randomIO thing
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment