5

I have been using Haskell for a year or so, and it is fantastic. I have recently started using Servant; and I would like to use an SQL-library such as Selda, so that everything is type-safe. (This is truely incredible when combined with Elm! :) )

There is an example here: https://github.com/dmjio/servant-selda of using Selda with Servant, but only for postgres. During initial development, I've found it can be really useful to use SQLite.

I feel this should be possible, but I can't seem to find any examples. I have tried to look at the type signatures, to understand how to pass SQLite as a Pool; but this is a little above my Haskell'ing skills!

Has anyone experience of doing with Selda, or had success using another typesafe sql library with Servant? I am open to using other libraries other than Selda; I would like to use UUID's as primary-keys, and Persistent wasn't too happy when I tried this.

Thanks

user2633351
  • 173
  • 4
  • Certainly not an answer but: Why is sqlite easier during development for you? I find `docker run -p 5432 postgres` to be really clean and allows me to work with the same API as production. Is it a resource constraint? A platform issue? – Thomas M. DuBuisson Sep 18 '19 at 15:58
  • 1
    Hi Thomas, this is the option I have gone for; I think it makes the most sense. – user2633351 Sep 30 '19 at 13:41

1 Answers1

0

Solution is to use SeldaT as your custom servant monad (based on https://docs.servant.dev/en/stable/cookbook/using-custom-monad/UsingCustomMonad.html)

Minimal example:

{-# LANGUAGE TypeApplications #-}

module Main where

import Control.Exception (bracket)
import Data.Aeson (ToJSON)
import Database.Selda (SeldaT)
import Database.Selda.Backend (SeldaConnection, runSeldaT)
import Database.Selda.SQLite (SQLite, seldaClose, sqliteOpen)
import Network.Wai.Handler.Warp (run)
import Servant (Application, EmptyAPI (EmptyAPI), Get, Handler, HasServer (ServerT), JSON, Proxy (Proxy), emptyServer, hoistServer, serve)

type YourAPI = EmptyAPI -- replace with your API type

yourApi :: Proxy YourAPI
yourApi = Proxy @YourAPI

type AppM = SeldaT SQLite Handler

server :: ServerT YourAPI AppM
server = emptyServer -- replace with your API implementation

nt :: SeldaConnection SQLite -> AppM a -> Handler a
nt = flip runSeldaT

app :: SeldaConnection SQLite -> Application
app conn = serve yourApi $ hoistServer yourApi (nt conn) server

main :: IO ()
main =
  bracket
    (sqliteOpen "sqlite.db")
    seldaClose
    (run 3000 . app)

Please note that concurrency support isn't well documented (and probably supported). Found this q/a that might give more details about sqlite concurrency in Haskell What are the rules about concurrently accessing a persistent database. Similarly to persistent-sqlite, selda-sqlite is depending on direct-sqlite as underlying library.

Jiri
  • 181
  • 1
  • 5