haskell facebook example - facebook

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.

Related

Haskell scotty Action to IO

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.

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.

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

Program architecture using the monad reader in Scala

I'm trying to wrap my head around dependency injection in Scala using monad readers. I started learning Scala recently, so the code I give here, does not compile, but I hope my problem becomes clear. To start, lets assume our application allows a user to changes it password. First, I create a simple case class User and add a changePassword method on the companion object:
case class User (id:Int, username:String, password:String)
object User {
def changePassword (oldPassword:String, newPassword:String, user:User) = {
if (!user.password.equals(oldPassword)) {
-\/("Old password incorrect")
} else {
\/-(user.copy(password = newPassword))
}
}
}
Note that the changePassword method is still a bit to specific in its return type. In Haskell I would write:
data User = User {
id :: Int
, username :: String
, password :: String
} deriving (Show)
changePassword :: (MonadError String m) => String -> String -> User -> m User
changePassword old new user =
if password user == old
then return $ user { password = new }
else throwError "Old password incorrect"
This would allow the changePassword function to be used in any monad transformer stack which contains the Error monad.
Now, to create the application we need two more additional components. One component is a repository which knows how to retrieve and store User objects. Multiple implementations may exists. For example we may have a database repository in production and a in memory repository for testing purposes.
trait UserRepository {
def getById(id:Int):M[User]
def save (user:User):M[Unit]
}
object DatabaseUserRepository extends UserRepository {
def getById(id:Int):MonadReader[Connection,User]
def save (user:User):MonadReader[Connection,Unit]
}
object InMemoryUserRepository extends UserRepository {
def getById(id:Int):MonadState[UserMap,User]
def save (user:User):MonadState[UserMap,Unit]
}
Both implementations are monadic, but the monadic behavior they need may differ. I.e. the database repository depends on a connection which its may access using the reader monad while the in memory repository depends on the state monad.
The other component is a service component which acts as entry point to our logic from the UI.
object UserService {
def doChangePassword (id:Int, oldPassword:String, newPassword:String):MonadReader[UserRepository, Unit]
}
This component uses the user repository to retrieve the user by the given id and then calls the changePassword function and saves the updated user object back using the repository.
I hope this illustrates what I try to achieve. However, I'm still a bit puzzled how to connect the different parts together...
To answer my own question, at least partially. I searched google for this topic and found out about the concept of a free monad:
http://www.haskellforall.com/2012/06/you-could-have-invented-free-monads.html
After reading this, I came up with:
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE FlexibleContexts #-}
module Main where
import Control.Monad.Free
import Control.Monad.Error
import Control.Monad.Identity
import Control.Monad.State hiding (get)
import qualified Control.Monad.State as MS
import Data.IntMap
import Prelude hiding (lookup)
data User = User {
ident :: Int
, username :: String
, password :: String
} deriving (Show, Eq, Ord)
changePassword' :: (MonadError String m) => String -> String -> User -> m User
changePassword' old new user =
if password user == old
then return $ user { password = new }
else throwError "Old password incorrect"
type UserMap = IntMap User
data Interaction next = Save User next
| Get Int (User -> next)
| ChangePassword String String User (User -> next)
instance Functor Interaction where
fmap f (Save user next) = Save user (f next)
fmap f (Get id g) = Get id (f . g)
fmap f (ChangePassword old new user g) = ChangePassword old new user (f . g)
type Program = Free Interaction
save :: User -> Program ()
save user = liftF (Save user ())
get :: Int -> Program User
get ident = liftF (Get ident id)
changePassword :: String -> String -> User -> Program User
changePassword old new user = liftF (ChangePassword old new user id)
doChangePassword :: String -> String -> Int -> Program ()
doChangePassword old new ident = get ident
>>= changePassword old new
>>= save
newtype ST a = ST { run :: StateT UserMap (ErrorT String Identity) a } deriving (Monad, MonadState UserMap, MonadError String)
runST :: ST a -> UserMap -> UserMap
runST (ST x) s = case runIdentity (runErrorT (execStateT x s)) of
Left message -> error message
Right state -> state
interpreter :: Program r -> ST r
interpreter (Pure r) = return r
interpreter (Free (Save user next)) = do
modify (\map -> insert (ident user) user map)
interpreter next
interpreter (Free (Get id g)) = do
userMap <- MS.get
case lookup id userMap of
Nothing -> throwError "Unknown identifier"
Just user -> interpreter (g user)
interpreter (Free (ChangePassword old new user g)) = do
user' <- changePassword' old new user
interpreter (g user')
main = (putStrLn . show) $ runST (interpreter p) (fromList [(1, User 1 "username" "secret")])
where
p = doChangePassword "secret" "new" 1
Here we define a small language consisting of three operations: Get, Save and ChangePassword. Then we define our function in terms of these 3 operations:
doChangePassword :: String -> String -> Int -> Program ()
doChangePassword old new ident = get ident
>>= changePassword old new
>>= save
The result of this function is simply a structure describing a small program which we need to execute. For this, we write a small interpreter. Changing from a database repository to an in memory repository is achieved by providing a different interpreter.
Composing multiple languages is possible by defining coproducts as described in data types a la carte (http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.101.4131&rep=rep1&type=pdf). But until now, I didn't have time yet to try this out.

Prompting for a password in Haskell command line application

The following Haskell program prompts the user for a password in the terminal and continues if he has entered the correct one:
main = do
putStrLn "Password:"
password <- getLine
case hash password `member` database of
False -> putStrLn "Unauthorized use!"
True -> do
...
Unfortunately, the password will appear on the screen as the user types it, which I want to avoid.
How can I read a sequence of characters that the users types without having the show up on the screen? What is the equivalent of getLine for this purpose?
I'm on MacOS X, but I would like this to work on Windows and Linux, too.
Do this:
module Main
where
import System.IO
import Control.Exception
main :: IO ()
main = getPassword >>= putStrLn . ("Entered: " ++)
getPassword :: IO String
getPassword = do
putStr "Password: "
hFlush stdout
pass <- withEcho False getLine
putChar '\n'
return pass
withEcho :: Bool -> IO a -> IO a
withEcho echo action = do
old <- hGetEcho stdin
bracket_ (hSetEcho stdin echo) (hSetEcho stdin old) action
There is a getPassword in System.Console.Haskeline. Probably it's an overkill for your case but someone may find it useful.
An example:
> runInputT defaultSettings $ do {p <- getPassword (Just '*') "pass:"; outputStrLn $ fromJust p}
pass:***
asd
It is possible to disable echoing in the terminal with the System.Posix.Terminal module. However, this requires POSIX support, so may not work on Windows (I didn't check).
import System.Posix.Terminal
import System.Posix.IO (stdInput)
getPassword :: IO String
getPassword = do
tc <- getTerminalAttributes stdInput
setTerminalAttributes stdInput (withoutMode tc EnableEcho) Immediately
password <- getLine
setTerminalAttributes stdInput tc Immediately
return password
main = do
putStrLn "Password:"
password <- getPassword
putStrLn "Name:"
name <- getLine
putStrLn $ "Your password is " ++ password ++ " and your name is " ++ name
Note that the stdin is line-buffered, so if you use putStr "Password:" instead of putStrLn, you need to flush the buffer first, otherwise the prompt will be inhibited also.
withEcho can be written with a little less noise:
withEcho :: Bool -> IO a -> IO a
withEcho echo action =
bracket (hGetEcho stdin)
(hSetEcho stdin)
(const $ hSetEcho stdin echo >> action)
As I commented above, I suggest you use haskeline, which is a full prompt library. I've used it happily for LambdaCalculator with no complaints.
I have found this useful when reading passwords:
import Control.Exception
import System.IO
withoutEcho :: IO a -> IO a
withoutEcho action =
finally (hSetEcho stdin False >> action) (hSetEcho stdin True)