Closed cideM closed 2 weeks ago
How about Internal/Examples.hs
? This is the file from which the Haddock examples are sourced. Does this file itself satisfy your requirements? If so I can link it from the README (or elsewhere if you have a suggestion). If not then what would you suggest changing to satisfy your requirements?
I think that this file is too big. Additionally, depending on Bluefin.Internal
seems like something people would want to avoid. Since it's hard to know what an average use case for this library is, I'd suggest to take the first example from the introduction and turn it into a mostly self contained example that includes a main
function (and whatever language extensions are required). It's a pretty common thing in Go packages and makes it trivial to get started.
Alternatively, using the smallest possible example that uses IO
might be closer to real world usage.
Ah yes, I see. You want some sort of getting started template?
In retrospect that's a much better title for this issue and yes that's what I had in mind! The documentation is already very good, especially for a Haskell project. I'm currently going through that getting started phase and while I can piece things together by looking at the various modules and figuring out where I can get each import from, following compiler errors for missing language extensions, and so on, but having all that wrapped up in one convenient example would mean the time it takes to go from "what's bluefin?" to having a runnable, editable example is just a few seconds.
OK great. Since you're already piecing something together, do you have something you could paste here (whether it works or not?) and we can collaboratively edit it into the form you'd like?
Here's an example showing what a database interaction could look like. I admit that this is biased towards web development and that I went against what I suggested above (using the counter example). Using a custom effect seems like something almost every user of the library would want. At least it should probably include some IO
. Do you think it's too involved?
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE TypeOperators #-}
module Main where
import Bluefin.Compound
import Bluefin.Eff (Eff, (:&), (:>))
import qualified Bluefin.Eff as BF
import Bluefin.Exception (Exception)
import qualified Bluefin.Exception as BF
import Bluefin.IO (IOE)
import qualified Bluefin.IO as BF
newtype DbHandle = DbHandle String deriving (Show)
newtype UserId = UserId String deriving (Show, Eq)
newtype User = User String deriving (Show)
data DbEff es = MkDbEff
{ queryImpl :: DbHandle -> UserId -> Eff es User
}
query :: (e :> es) => DbEff e -> DbHandle -> UserId -> Eff es User
query db dbHandle userId = useImpl $ queryImpl db dbHandle userId
runDbEffIo ::
forall exEff dbEff es r.
(exEff :> es, dbEff :> es) =>
Exception String exEff ->
IOE dbEff ->
(forall e. DbEff e -> Eff (e :& es) r) ->
Eff es r
runDbEffIo ex _ fn =
useImplIn
fn
( MkDbEff
{ queryImpl = \_ userId -> do
if userId == UserId "1"
then pure $ User "Alice"
else BF.throw ex "not found"
}
)
main :: IO ()
main = do
let dbHandle = DbHandle "db"
result <- BF.runEff $ \io -> BF.try $ \ex ->
runDbEffIo ex io $ \db -> do
u1 <- query db dbHandle (UserId "1")
BF.effIO io $ print u1
u2 <- query db dbHandle (UserId "2")
BF.effIO io $ print u2
case result of
Left err -> print err
Right _ -> print "success"
Turning the counter example into a runnable file adds very little
module Main where
import qualified Bluefin.Eff as BF
import qualified Bluefin.State as BF
import Control.Monad (when)
main :: IO ()
main = print $
BF.runPureEff $
BF.evalState (5 :: Integer) $ \state -> do
counter <- BF.get state
when (counter < 10) $
BF.modify state (+ 10)
BF.get state
Here's an example showing what a database interaction could look like
Ah great, I think that looks nice. Should I incorporate that straight into an template package/module in the repository?
Turning the counter example into a runnable file adds very little
Do you mean you don't think it's worth adding that example?
Ah great, I think that looks nice. Should I incorporate that straight into an template package/module in the repository?
That sounds good 🙏🏻
Do you mean you don't think it's worth adding that example?
Yes, I think having one runnable example should be enough, since especially the small snippets need very little to no additional code.
By the way, effect systems were always pretty intimidating because of all the type magic going on. Bluefin is comparatively simple and the examples and documentation really help. Great work ⭐
@cideM could you have a look at this? https://github.com/tomjaguarpaw/bluefin/pull/19
By the way, effect systems were always pretty intimidating because of all the type magic going on. Bluefin is comparatively simple and the examples and documentation really help. Great work ⭐
That's really great to hear! That was my hope :) Please do continue to give feedback about how I can make it even simpler or to help people get started.
Closed in #19 3001d7ca840d552f3ca6470f32d0103e1b3e6810
Maybe I just didn't know where to look but there seems to be no complete, self contained example, such as a
Main.hs
file showing necessaryLANGUAGE
pragmas and where to get typical imports from. It's great that the documentation has examples, and I think this project would be even more approachable if it had one blob of code you can just copy into your editor and modify it.