Haskell scotty Action to IO - mongodb

I am back again trying to learn Haskell and, oh boy it is difficult!
I am a trying to do a simple mongoDB insertion inside a Scotty endpoint. Problem is the type return by the insert function is not accepted in the Scotty do statement. The program is quite simple:
{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty
import Data.Monoid (mconcat)
import Control.Monad.Trans(liftIO,lift,MonadIO)
import System.IO
import Data.Text.Lazy.Encoding (decodeUtf8)
import Data.Text.Lazy (pack,unpack)
import Data.Maybe
import Data.Time.Clock.POSIX
import Database.MongoDB (Action, Document, Document, Value, access,
allCollections,insert, close, connect, delete, exclude, find,
host,findOne, insertMany, master, project, rest,
select, liftDB, sort, Val, at, (=:))
main :: IO ()
main = scotty 3000 $ do
post "/logs" $ do
id <- liftIO $ getTimeInMillis
b <- body
let decodedBody = unpack(decodeUtf8 b)
i <- liftIO $ insertLog id decodedBody
text $ "Ok"
--setup database connection
run::MonadIO m => Action m a -> m a
run action = do
pipe <- liftIO(connect $ host "127.0.0.1")
access pipe master "data" action
getTimeInMillis ::Integral b => IO b
getTimeInMillis = round `fmap` getPOSIXTime
insertLog::MonadIO m => Int -> String -> Action m Value
insertLog id body = run $ insert "logs" ["id" =: id, "content" =: body]
the problem comes in the line
i <- liftIO $ insertLog id decodedBody
And the type error is
Expected type: Web.Scotty.Internal.Types.ActionT
Data.Text.Internal.Lazy.Text IO Value
Actual type: Action m0 Value
Any help or tip will be welcome!

I see a different error message with that code. Maybe you made some changes (like adding liftIO).
• Couldn't match type ‘Control.Monad.Trans.Reader.ReaderT
Database.MongoDB.Query.MongoContext m0 Value’
with ‘IO a0’
Expected type: IO a0
Actual type: Action m0 Value
In the line:
i <- liftIO $ insertLog id decodedBody
the liftIO function expects a genuine IO action, of type IO a for some a. However, the expression insertLog id decodedBody doesn't represent an IO action. It is Mongo action of type Action m Value for some m that has a MonadIO constraint. You need to use some function run Mongo Action values in IO. It looks like you've already written such a function, named run. It's written for a general MonadIO m but can be specialized to:
run :: Action IO a -> IO a
so if you first run your Mongo action (to turn it into IO) and then lift that action (to run it in the Scotty action under post), the following should type check:
i <- liftIO $ run $ insertLog id decodedBody
Update: Whoops! I missed the run in the insertLog function. You either want to write:
-- use "run" here
main = do
...
i <- liftIO $ run $ insertLog id decodedBody
-- but no "run" here
insertLog::MonadIO m => Int -> String -> Action m Value
insertLog id body = insert "logs" ["id" =: id, "content" =: body]
OR you want to write:
-- no "run" here
main = do
...
i <- liftIO $ insertLog id decodedBody
-- change the type signature and use "run" here
insertLog :: Int -> String -> IO Value
insertLog id body = run $ insert "logs" ["id" =: id, "content" =: body]
That will avoid the double-run problem.
The reason run didn't work as intended in your original code is a little complicated...
The problem is that run has flexibility to convert its Mongo action to many possible monads by returning m a for any m that supports MonadIO m. Because you gave insertLog a type signature with return type MonadIO m' => Action m' Value (where I changed the variable to keep m and m' distinct), the type checker matched the return type of run to the return type of insertLog:
m a ~ Action m' Value
by setting a ~ Value and m ~ Action m'. So, your run in insertLog was actually used with the following bizarre type:
run :: Action (Action m') Value -> Action m' Value
Normally, this would have caused a type error, but the type of insert is also flexible. Instead of returning an action of type Action IO Value, which would be the "usual" type, it happily adapted itself to return an action of type Action (Action IO) Value to match what run was expecting.

Related

Abstract result types in Free Monads

Suppose we want to define a simple DSL for defining UI interactions where we can create objects and then select them:
object TestCommand {
sealed trait EntityType
case object Project extends EntityType
case object Site extends EntityType
sealed trait TestCommand[A, E]
case class Create[A, E](entityType: EntityType, withEntity: E => A) extends TestCommand[A, E]
case class Select[A, E](entity: E, next: A) extends TestCommand[A, E]
}
The problem I have is that I wouldn't want to specify what the return type of the creation command should be (E above). I would like to let this decision up to the interpreter. For instance, E could be a string, or a Future if we are creating objects with asynchronous REST calls.
If I try to define the DSL in the usual way using liftF as shown below:
object TestDSL {
def create[E](entityType: EntityType): Free[TestCommand[?, E], E] =
Free.liftF(Create(entityType, identity: E => E): TestCommand[E, E])
def select[E](entity: E): Free[TestCommand[?, E], Unit] =
Free.liftF(Select[Unit, E](entity, ()))
}
I get the following error:
Error:(10, 10) no type parameters for method liftF: (value: S[A])scalaz.Free[S,A] exist so that it can be applied to arguments (dsl.TestCommand.TestCommand[E,E])
--- because ---
argument expression's type is not compatible with formal parameter type;
found : dsl.TestCommand.TestCommand[E,E]
required: ?S[?A]
Free.liftF(Create(entityType, identity: E => E): TestCommand[E, E])
I cannot understand what is going wrong in the code above, but a more important question is whether this is the right way to abstract over the types appearing in free monads. If not, what is the right (functional) approach?
EDIT:
In Haskell the approach described above works without a problem:
{-# LANGUAGE DeriveFunctor #-}
-- |
module TestDSL where
import Control.Monad.Free
data EntityType = Project | Site
data TestCommand e a = Create EntityType (e -> a) | Select e a
deriving Functor
-- | The DSL
create :: EntityType -> Free (TestCommand e) e
create et = liftF $ Create et id
select :: e -> Free (TestCommand e) ()
select e = liftF $ Select e ()
-- | A sample program:
test :: Free (TestCommand e) ()
test = do
p <- create Project
select p
_ <- create Site
return ()
-- | A trivial interpreter.
interpTestCommand :: TestCommand String a -> IO a
interpTestCommand (Create Project withEntity) = do
putStrLn $ "Creating a project"
return (withEntity "Project X")
interpTestCommand (Create Site withEntity) = do
putStrLn $ "Creating a site"
return (withEntity "Site 51")
interpTestCommand (Select e next) = do
putStrLn $ "Selecting " ++ e
return next
-- | Running the interpreter
runTest :: IO ()
runTest = foldFree interpTestCommand test
Running the test will result in the following output:
λ> runTest
Creating a project
Selecting Project X
Creating a site
Right now you have test :: Free (TestCommand e) (). This means that the type of the entity e can be anything the caller wants, but it's fixed throughout the computation.
But that's not right! In the real world, the type of the entity that's created in response to a Create command depends on the command itself: if you created a Project then e should be Project; if you created a Site then e should be Site. So e shouldn't be fixed over the whole computation (because I might want to create Projects and Sites), and it shouldn't be up to the caller to pick an e.
Here's a solution in which the type of the entity depends on the value of the command.
data Site = Site { {- ... -} }
data Project = Project { {- ... -} }
data EntityType e where
SiteTy :: EntityType Site
ProjectTy :: EntityType Project
The idea here is that pattern-matching on an EntityType e tells you what its e is. In the Create command we'll existentially package up an entity e along with a bit of GADT evidence of the form EntityType e which you can pattern-match on to learn what e was.
data CommandF r where
Create :: EntityType e -> (e -> r) -> CommandF r
Select :: EntityType e -> e -> r -> CommandF r
instance Functor CommandF where
fmap f (Create t next) = Create t (f . next)
fmap f (Select t e next) = Select t e (f next)
type Command = Free CommandF
create :: EntityType e -> Command e
create t = Free (Create t Pure)
select :: EntityType e -> e -> Command ()
select t e = Free (Select t e (Pure ()))
myComputation :: Command ()
myComputation = do
p <- create ProjectTy -- p :: Project
select ProjectTy p
s <- create SiteTy -- s :: Site
return ()
When the interpreter reaches a Create instruction, its job is to return an entity of the type that matches the wrapped EntityType. It has to inspect the EntityType in order to know what e is and behave appropriately.
-- assuming createSite :: IO Site and createProject :: IO Project
interp :: CommandF a -> IO a
interp (Create SiteTy next) = do
site <- createSite
putStrLn "created a site"
return (next site)
interp (Create ProjectTy next) = do
project <- createProject
putStrLn "created a project"
return (next project)
-- plus clauses for Select
I don't know how this would translate into Scala exactly, but that's the gist of it in Haskell.

How do I use a persistent State monad with Spock?

I'm just starting out with haskell and I'm having issues with a basic "echo" REST server.
Spock looked like a nice starting place for a REST server, and I though I got the basics of the State monad, but I'm having issues understanding how to put a runState around the spock code.
Here's the code I've got so far.
{-# LANGUAGE OverloadedStrings #-}
module Main where
import Data.Monoid
import Web.Spock.Safe
import qualified Control.Monad.State as S
storeData :: String -> S.State String String
storeData val = do S.put val
return val
getData :: S.State String String
getData = do val <- S.get
return val
main :: IO ()
main =
runSpock 11350 $ spockT id $
do get "store" $
text "Would be a call to getData"
OK so here's a version of the restartableStateT hack for your example:
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE Rank2Types #-}
module Main where
import Data.Monoid
import Data.String (fromString)
import Web.Spock.Safe
import qualified Control.Monad.State as S
import Data.IORef
storeData :: (Monad m) => String -> S.StateT String m String
storeData val = do S.put val
return val
getData :: (Monad m) => S.StateT String m String
getData = do val <- S.get
return val
newtype RunStateT s m = RunStateT{ runStateT :: forall a. S.StateT s m a -> m a }
restartableStateT :: s -> IO (RunStateT s IO)
restartableStateT s0 = do
r <- newIORef s0
return $ RunStateT $ \act -> do
s <- readIORef r
(x, s') <- S.runStateT act s
atomicModifyIORef' r $ const (s', x)
main :: IO ()
main = do
runner <- restartableStateT "initial state"
runSpock 11350 $ spockT (runStateT runner) $ do
get "store" $ do
cmd <- param "value"
case cmd of
Nothing -> do
old <- S.lift getData
text $ fromString old
Just new -> do
S.lift $ storeData new
text "Stored."
Like the other answer, this one creates a single global IORef to store "the state". The runner passed to spockT is then able to run any StateT String IO computation by getting the state from this IORef, running the computation, and putting the resulting state back into the IORef.
I would like to reiterate from the other answer that this is not necessarily a good idea, because it has no story for concurrency. I guess that could be papered over by using STM for example, but... I think you should just use a database for this kind of thing.

How to use Applicative for concurrency?

This is a follow-up to my previous question. I copied the example below from Haxl
Suppose I am fetching data from a blog server to render a blog page, which contains the recent posts, popular posts and posts topics.
I have the following Data Fetching API:
val getRecent : Server => Seq[Post] = ...
val getPopular : Server => Seq[Post] = ...
val getTopics : Server => Seq[Topic] = ...
Now I need to compose them to implement a new function getPageData
val getPageData: Server => (Seq[Post], Seq[Post], Seq[Topic])
Haxl suggests using a new monad Fetch to make the API composable.
val getRecent : Fetch[Seq[Posts]] = ...
val getPopular : Fetch[Seq[Posts]] = ...
val getTopics : Fetch[Seq[Topic]] = ...
Now I can define my getPageData: Fetch[A] with monadic composition
val getPageData = for {
recent <- getRecent
popular <- getPopular
topics <- getTopics
} yield (recent, popular, topics)
but it does not run getRecent, getPopular, and getTopics concurrently.
Haxl suggests using applicative composition <*> to compose "concurrent" functions (i.e. the functions that can run concurrently). So my questions are:
How to implement getPageData assuming Fetch[A] is an Applicative ?
How to implement Fetch as an Applicative but not a Monad ?
How to implement getPageData assuming Fetch[A] is an Applicative ?
All we need to do is drop the monadic bind >>= in favour of the applicative <*>. So instead of
val getPageData = for {
recent <- getRecent
popular <- getPopular
topics <- getTopics
} yield (recent, popular, topics)
we would write something like (in Haskell syntax; sorry, I can't do Scala off the top of my head):
getPageData = makeTriple <$> getRecent <*> getPopular <*> getTopics
where
makeTriple x y z = (x, y, z)
But whether this has the desired effect is contingent upon the second question!
How to implement Fetch as an Applicative but not a Monad ?
The key distinction between monadic and applicative sequencing is that the monadic one can depend upon the value inside a monadic value, whereas the applicative <*> cannot. Notice how the monadic expression for getPageData above binds the names recent and popular before reaching getTopics. Those names could have been used to change the structure of the expression, for example by getting some other data source in case recent is empty. But with the applicative expression, the results of getRecent and getPopular are not factors in the structure of the expression itself. This property allows us to fire off each term in the applicative expression concurrently, because we know the structure of the expression statically.
So, using the observation above, and obviously the particular shape of the Fetch datatype, we can come up with a suitable definition for <*>. I think the following illustrates the general idea:
data Fetch a = Fetch { runFetch :: IO a }
fetchF <*> fetchX = Fetch $ do
-- Fire off both IOs concurrently.
resultF <- async $ runFetch fetchF
resultX <- async $ runFetch fetchX
-- Wait for both results to be ready.
f <- wait resultF
x <- wait resultX
return $ f x
For comparison, suppose we tried to do monadic bind with concurrent evaluation:
fetchF >>= fetchK = Fetch $ do
resultF <- async $ runFetch fetchF
-- Oh no, we need resultF in order to produce the next
-- Fetch value! We just have to wait...
f <- wait resultF
fetchX <- async $ runFetch (fetchK f)
x <- wait $ runFetch fetchX
return $ f x

Scotty Using MongoDB

I'm relatively new to Haskell, and this is my first time working with monad transformers. I'd really appreciate some help.
runQuery :: Pipe -> Query -> ActionM (Either Failure [Document])
runQuery pipe query = access pipe master "nutrition" (find query >>= rest)
main = do
pipe <- runIOE $ connect $ host "127.0.0.1"
scotty 3000 $ do
post "/" $ do
b <- body
let user :: Either String User = eitherDecode b
case user of
Left err -> text . pack $ "Could not decode the user:" ++ err ++ ":\n" ++ (show b)
Right u -> do
let query::Query = (select ["i_name" =: ["$in" =: map (unpack . name) (foods u)]] "stock_foods")
results <- runQuery pipe query
...
I'm trying to query a mongodb database under the scotty web framework, but I'm getting an error about MonadBaseControl. Do I really have to make an instance of this to connect to a database with scotty, and how would I go about doing it?
No instance for (MonadBaseControl
IO (scotty-0.7.2:Web.Scotty.Types.ActionT Text IO))
arising from a use of `find'
Possible fix:
add an instance declaration for
(MonadBaseControl
IO (scotty-0.7.2:Web.Scotty.Types.ActionT Text IO))
mongoDB is generic enough to work in any monad that is instance of MonadBaseControl IO and MonadIO.
For example, you can choose IO monad. In this case you need liftIO . runQuery inside scotty's action:
import Web.Scotty
import Database.MongoDB
import qualified Data.Text.Lazy as T
import Control.Monad.IO.Class
runQuery :: Pipe -> Query -> IO [Document]
runQuery pipe query = access pipe master "nutrition" (find query >>= rest)
main = do
pipe <- connect $ host "127.0.0.1"
scotty 3000 $ do
get "/" $ do
res <- liftIO $ runQuery pipe (select [] "stock_foods")
text $ T.pack $ show res
After #Sebastian Philipp added MonadBaseControl instance for Scotty.ActionT, there is no need to lift anything. You can transparently work with mongoDB form scotty. Just change type signature and drop liftIOs:
runQuery :: Pipe -> Query -> ActionM [Document]
...
get "/" $ do
res <- runQuery pipe (select [] "stock_foods")
text $ T.pack $ show res

haskell facebook example

I am stuck with haskell types.
{-# LANGUAGE OverloadedStrings #-}
module Main (
main
) where
import qualified Facebook as FB
import Network.HTTP.Conduit (withManager)
import Control.Monad.IO.Class (liftIO)
import System.IO
app :: FB.Credentials
app = FB.Credentials "localhost" "249348058430770" "..."
url :: FB.RedirectUrl
url = "http://localhost/fb"
perms :: [FB.Permission]
perms = ["user_about_me", "email"]
main :: IO ()
main = do
fbAuthUrl <- FB.getUserAccessTokenStep1 url perms
liftIO $ print fbAuthUrl
argument <- readLn
token <- FB.getUserAccessTokenStep2 url [argument]
withManager $ \manager -> do
FB.runFacebookT app manager $ do
u <- FB.getUser "me" [] token
liftIO $ print (FB.userEmail u)
error
src/Main.hs:23:18:
Couldn't match expected type `IO t0'
with actual type `FB.FacebookT
FB.Auth m0 text-0.11.2.0:Data.Text.Internal.Text'
In the return type of a call of `FB.getUserAccessTokenStep1'
In a stmt of a 'do' block:
fbAuthUrl <- FB.getUserAccessTokenStep1 url perms
In the expression:
do { fbAuthUrl <- FB.getUserAccessTokenStep1 url perms;
liftIO $ print fbAuthUrl;
argument <- readLn;
token <- FB.getUserAccessTokenStep2 url [argument];
.... }
package http://hackage.haskell.org/package/fb
First, let me preface this answer by the disclaimer that I've never actually used the Facebook API or the Conduits library, so I'm not sure if this code actually does anything sensible, but by going with just the type information, I think this is what you were trying to do
main :: IO ()
main = withManager $ \manager -> FB.runFacebookT app manager $ do
fbAuthUrl <- FB.getUserAccessTokenStep1 url perms
liftIO $ print fbAuthUrl
argument <- liftIO $ readLn
token <- FB.getUserAccessTokenStep2 url [argument]
u <- FB.getUser "me" [] (Just token)
liftIO $ print (FB.userEmail u)
The main pitfall is that main in Haskell must always have the type IO a, but you are trying to use a value of type FacebookT Auth m () as your main. Your implementation is on the right track, but the runFacebookT and withManager need to be the first thing in the function.
Type-wise, the actual do-block has the type FacebookT Auth (ResourceT IO) (). The runFacebookT function is used to unwrap the FacebookT transformer, resulting in a ResourceT IO () value, which is in turn processed by withManager to produce a plain old IO ().
One additional problem was that you originally had a readLn in your do-block without liftIO, which was confusing the type-inference. I also added the missing Just to the FB.getUser call.