After reading this I tried
{-# LANGUAGE OverloadedStrings, NoMonomorphismRestriction #-}
module Login (
fbUrl,
fbEmail
) where
-- package http://hackage.haskell.org/package/fb
import qualified Facebook as FB
import Network.HTTP.Conduit (withManager)
app :: FB.Credentials
app = FB.Credentials "localhost" "249348058430770" "..."
url :: FB.RedirectUrl
url = "http://localhost/fb"
perms :: [FB.Permission]
perms = ["user_about_me", "email"]
--fbUrl :: Monad m => FB.FacebookT FB.Auth m Text
fbUrl :: IO Text
fbUrl = withManager $ \manager -> FB.runFacebookT app manager $ FB.getUserAccessTokenStep1 url perms
--fbEmail :: Monad m => (ByteString, ByteString) -> FB.FacebookT FB.Auth m (Maybe Text)
--fbEmail :: (ByteString, ByteString) -> IO (Maybe Text)
fbEmail c = withManager $ \manager -> FB.runFacebookT app manager $ do
t <- FB.getUserAccessTokenStep2 url [c]
u <- FB.getUser "me" [] (Just t)
return $ FB.userEmail u
module Main (
main
) where
import Login
import qualified Data.ByteString.Char8 as C
import Control.Exception
main :: IO ()
main = do
let a = ("code","test")
e <- fbEmail $ (\(x,y) -> (C.pack x, C.pack y)) a
case e of
Nothing -> print "doh!"
Just e -> print e
I get haskell-facebook: FacebookException {fbeType = "invalid_code", fbeMessage = "Invalid verification code format."} instead of doh!
With e <- try (fbEmail $ (\(x,y) -> (C.pack x, C.pack y)) a) i get
Couldn't match expected type `Either
e0 (Maybe Data.Text.Internal.Text)'
with actual type `Maybe t0'
In the pattern: Nothing
In a case alternative: Nothing -> print "doh!"
In a stmt of a 'do' block:
case e of {
Nothing -> print "doh!"
Just e -> print e }
#Daniel Fischer
let a = ("code","test")
e <- try (fbEmail $ (\(x,y) -> (C.pack x, C.pack y)) a)
case e of
Left x -> print "doh!"
Right e -> print "ok"
Ambiguous type variable `e0' in the constraint:
(Exception e0) arising from a use of `try'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' block:
e <- try (fbEmail $ (\ (x, y) -> (C.pack x, C.pack y)) a)
In the expression:
do { let a = ...;
e <- try (fbEmail $ (\ (x, y) -> (C.pack x, C.pack y)) a);
case e of {
Left x -> print "doh!"
Right e -> print "ok" } }
In an equation for `main':
main
= do { let a = ...;
e <- try (fbEmail $ (\ (x, y) -> (C.pack x, C.pack y)) a);
case e of {
Left x -> print "doh!"
Right e -> print "ok" } }
When I add a type signature fbEmail :: Monad m => (ByteString, ByteString) -> FB.FacebookT FB.Auth m (Maybe Text) I get
Could not deduce (monad-control-0.3.1.3:Control.Monad.Trans.Control.MonadBaseControl
IO m,
resourcet-0.3.2.2:Control.Monad.Trans.Resource.MonadUnsafeIO m,
Control.Monad.IO.Class.MonadIO m,
resourcet-0.3.2.2:Control.Monad.Trans.Resource.MonadThrow
(FB.FacebookT FB.Auth m))
arising from a use of `withManager'
from the context (Monad m)
bound by the type signature for
fbEmail :: Monad m =>
(ByteString, ByteString) -> FB.FacebookT FB.Auth m (Maybe Text)
at src/Login.hs:(25,1)-(28,27)
Possible fix:
add (monad-control-0.3.1.3:Control.Monad.Trans.Control.MonadBaseControl
IO m,
resourcet-0.3.2.2:Control.Monad.Trans.Resource.MonadUnsafeIO m,
Control.Monad.IO.Class.MonadIO m,
resourcet-0.3.2.2:Control.Monad.Trans.Resource.MonadThrow
(FB.FacebookT FB.Auth m)) to the context of
the type signature for
fbEmail :: Monad m =>
(ByteString, ByteString) -> FB.FacebookT FB.Auth m (Maybe Text)
or add instance declarations for
(monad-control-0.3.1.3:Control.Monad.Trans.Control.MonadBaseControl
IO m,
resourcet-0.3.2.2:Control.Monad.Trans.Resource.MonadThrow
(FB.FacebookT FB.Auth m))
In the expression: withManager
In the expression:
withManager
$ \ manager
-> FB.runFacebookT app manager
$ do { t <- FB.getUserAccessTokenStep2 url [...];
u <- FB.getUser "me" [] (Just t);
.... }
In an equation for `fbEmail':
fbEmail c
= withManager
$ \ manager
-> FB.runFacebookT app manager
$ do { t <- FB.getUserAccessTokenStep2 url ...;
.... }
When I add fbEmail :: (ByteString, ByteString) -> IO (Maybe Text) I get
Ambiguous type variable `e0' in the constraint:
(Exception e0) arising from a use of `try'
Probable fix: add a type signature that fixes these type variable(s)
In a stmt of a 'do' block:
e <- try (fbEmail $ (\ (x, y) -> (C.pack x, C.pack y)) a)
In the expression:
do { couchTest;
u <- fbUrl;
print u;
let a = ...;
.... }
In an equation for `main':
main
= do { couchTest;
u <- fbUrl;
print u;
.... }
try adds another layer on top of your result. To make this example simple, I'm catching all exceptions by using the catch-all SomeException.
To make it a bit more clear, here are the result types with type signatured added:
e :: Maybe Text <- fbEmail $ (\(x,y) -> (C.pack x, C.pack y)) a
Compared to this use of try with the exception type equal to SomeException:
e :: Either SomeException (Maybe Text) <- fbEmail $ (\(x,y) -> (C.pack x, C.pack y)) a
It's simple to deal with these more complex types using pattern matching as Daniel mentioned in his comments:
{-# LANGUAGE FlexibleContexts, OverloadedStrings #-}
module Main where
import Control.Exception
import qualified Data.ByteString.Char8 as C
import Data.Text
import Network.HTTP.Conduit (withManager)
import qualified Facebook as FB
app :: FB.Credentials
app = FB.Credentials "localhost" "249348058430770" "..."
url :: FB.RedirectUrl
url = "http://localhost/fb"
perms :: [FB.Permission]
perms = ["user_about_me", "email"]
fbUrl :: IO Text
fbUrl = withManager $ \manager -> FB.runFacebookT app manager $ FB.getUserAccessTokenStep1 url perms
fbEmail :: FB.Argument -> IO (Maybe Text)
fbEmail c = withManager $ \manager -> FB.runFacebookT app manager $ do
t <- FB.getUserAccessTokenStep2 url [c]
u <- FB.getUser "me" [] (Just t)
return $ FB.userEmail u
main :: IO ()
main = do
let a = ("code","test")
e <- try . fbEmail $ (\(x,y) -> (C.pack x, C.pack y)) a
case e of
Left e -> print $ "error: " ++ show (e :: SomeException)
Right Nothing -> print "doh!"
Right (Just e) -> print e
Related
With the following code insertRnd works properly but I can't get scramble or anything else that uses insertRnd to compile:
scramble :: ∀ eff. String -> Eff (random :: RANDOM | eff) String
scramble s = foldl insertRnd (take 1 s) (drop 1 s)
insertRnd :: ∀ eff. String -> String -> Eff (random :: RANDOM | eff) String
insertRnd st ch = do
n <- randomInt 0 $ length st
pure $ insertAt n ch st
I get the following error message
Could not match type
Eff
( random :: RANDOM
| t2
)
String
with type
String
while checking that type forall eff.
String
-> String
-> Eff
( random :: RANDOM
| eff
)
String
is at least as general as type t0 -> t1 -> t0
while checking that expression insertRnd
has type t0 -> t1 -> t0
in value declaration scramble
where t0 is an unknown type
t1 is an unknown type
t2 is an unknown type
What am I doing wrong?
First, your insertRnd itself doesn't compile for me, because there is no function insertAt :: Int -> String -> String -> String (or even Int -> Char -> String -> String, see below). There is such function for arrays and lists and some other stuff, but not for strings. I will just assume here that you wrote such function yourself and it exists in your code.
Second, even if it does compile, it has wrong signature for a fold: you're trying to fold over a String, which contains Chars, which means that the folding function's second argument must be a Char. So here I'll assume that your insertRnd actually has the following signature:
insertRnd :: ∀ eff. String -> Char -> Eff (random :: RANDOM | eff) String
Third, you can't actually foldl over a String, because String doesn't have an instance of Foldable. To fold over the characters of a string, you need to first convert the string to an array (or some other container) of Char. Fortunately, there is a helpful function for that - toCharArray.
Fourth, your claim about not being able to compile "anything else that uses insertRnd" is probably too broad. Here's a perfectly compilable example of "anything else" that uses insertRnd:
main = launchAff do
x <- liftEff $ insertRnd "abcd" 'x'
log x
And finally, the reason that your foldl doesn't compile is that foldl expects a pure function a -> b -> a as first argument, but you're giving it an effectful function a -> b -> Eff _ a. No wonder there is a type mismatch!
The effectful analog of foldl is foldM. This function does a similar thing, except it chains the calls within a monad instead of doing pure functional composition. For example:
foldM insertRnd "a" ['b', 'c', 'd']
Applying all of the above to your code, here's the final version (assuming the existence of insertAt :: Int -> Char -> String -> String):
scramble :: ∀ eff. String -> Eff (random :: RANDOM | eff) String
scramble s = foldM insertRnd (take 1 s) (toCharArray $ drop 1 s)
insertRnd :: ∀ eff. String -> Char -> Eff (random :: RANDOM | eff) String
insertRnd st ch = do
n <- randomInt 0 $ length st
pure $ insertAt n ch st
In a scenario like this, I want a single expression to resolve to multiple instances:
Inductive SR: Prop := Sen | Inf.
Parameter CA S: Prop.
Parameter X: SR -> CA -> Prop -> Prop.
Parameter X': SR -> CA -> Prop -> Set.
Parameter XP: SR -> CA -> Prop -> Type.
Definition iX' (t:bool): SR -> CA -> Prop -> Type := if t then X' else XP.
Context `{b:bool}`{c:bool}`{d:bool}`{s:SR}`{t:SR}`{u:SR}`{k:CA}`{l:CA}`{m:CA}`{o:Prop}`{p:Prop}`{q:Prop}.
Parameter foo: iX' b s k o.
Parameter foo'': iX' d u m q.
Parameter ss: S.
Class CON (f:bool) := an: if f then iX' b s k o -> iX' c t l p -> iX' d u m q else S -> S -> S.
Instance coni: CON true := fun (_:iX' b s k o) (_:iX' c t l p) => foo''.
Instance conj: CON false := fun (_:S) (_:S) => ss.
Check (_: CON false) ss.
Check (_: CON true) foo.
Check (_: CON _) ss.
Check (_: CON _) foo. (*Error: The term "foo" has type "iX' b s k o" while it is expected to have type "S".*)
Is there a way to make the instance resolution work w/ both (_: CON _) foo and (_: CON _) ss? If not, try to succeed in a scenario where the class and/or instances are different, while ... in Check ... ss and Check ... foo is identical, and resolves to functions fun (_:S) (_:S) => ss and fun (_:iX' b s k o) (_:iX' c t l p) => foo'', resp.
Is there any reason to restrict yourself to instances here? If you're already doing this much hackery, you might as well go a bit further and use tactics in terms in notations.
Ltac mkcon arg :=
match constr:(Set) with
| _ => exact ((_ : CON false) arg)
| _ => exact ((_ : CON true) arg)
end.
Notation CON_ arg := ltac:(mkcon arg) (only parsing).
Check (_: CON false) ss.
Check (_: CON true) foo.
Check CON_ ss.
Check CON_ foo.
I'm building a game in Purescript, using purescript-signal, which includes movement. The user presses the left/right key to move left/right. Minimal code is below.
It looks like purescript is evaluating the signal over "from the beginning of time" every step, which is baffling me. For example, if I keep pressing the right key at the beginning, the output is
m: 0
m: 0
m: 1
m: 0
m: 1
m: 2
m: 0
m: 1
m: 2
m: 3
rather than
m: 0
m: 1
m: 2
m: 3
as I would expect. How do I fix this?
module SimpleMove where
import Prelude
import Control.Monad.Eff (Eff)
import Control.Monad.Eff.Console (CONSOLE, log)
import Data.Functor
import Data.Int
import Signal (Signal, runSignal, foldp, sampleOn, map2)
import Signal.DOM (keyPressed)
import Signal.Time (Time, second, every)
import Partial.Unsafe (unsafePartial)
--MODEL
type Model = Int
step :: forall e. Partial => Int -> Eff (console :: CONSOLE | e) Model -> Eff (console :: CONSOLE| e) Model
step dir m' =
do
m <- m'
log ("m: " <> (show m))
pure (m + dir)
--SIGNALS
inputDir :: Eff _ (Signal Int)
inputDir =
let
f = \l r -> if l
then -1
else if r
then 1
else 0
in
map2 f <$> (keyPressed 37) <*> (keyPressed 39)
input :: Eff _ (Signal Int)
input = sampleOn (every second) <$> inputDir
--MAIN
main :: Eff _ Unit
main =
unsafePartial do
dirSignal <- input
let game = foldp step (pure 0) dirSignal
runSignal (map void game)
If you change your main and step like this you'll get the expected result:
main :: Eff _ Unit
main = do
dirSignal <- input
let game = foldp step 0 dirSignal
runSignal (map render game)
step :: forall e. Int -> Model -> Model
step dir m = m + dir
render :: forall e. Model -> Eff (console :: CONSOLE| e) Unit
render m = logShow m
I'm trying to use the STStrMap purescript module to maintain a map for a long running server application. It's a very simple String map. Here is what I have so far:
import Data.StrMap.ST (new, STStrMap, poke)
import Control.Monad.ST (ST, runST)
type MyMap = forall h e. Eff ( st :: ST h | e) (STStrMap h String)
myMap :: MyMap
myMap = new
-- pokeAString :: String -> String -> MyMap ??
pokeAString k v = poke k v myMap
The signature of MyMap is Eff, but poke expects a STStrMap as the first parameter. I'm not sure how to code this correctly. Note: I'm a newbie to purescript.
The STStrMap you initialize has side effects tracked by the Eff monad, so we have to use its instance of bind to run our computations (e.g. peek, poke), which has the type:
forall e a b. Eff e a -> (a -> Eff e b) -> Eff e b
In psci you can see how this works:
import Prelude
import Data.StrMap.ST
let myMap = new
let myPoke x = x >>= (\m -> poke m "key" "value")
let myPeek x = x >>= (\m -> peek m "key")
myPeek $ myPoke myMap
So your code becomes something like:
import Prelude
import Data.StrMap.ST (new, STStrMap, poke)
import Control.Monad.ST (ST)
import Control.Monad.Eff (Eff)
type MyMap = forall h e. Eff ( st :: ST h | e) (STStrMap h String)
myMap :: MyMap
myMap = new
pokeAString :: String -> String -> MyMap
pokeAString k v = do
a <- myMap
poke a k v
renderYaml :: forall a p e.
Yaml -> Registry p a (err :: Exception | e) -> Eff (err :: Exception | e) Unit
renderYaml yaml r = let
yamlToForeign :: Yaml -> Either String Foreign
yamlToForeign = runFn3 parseYaml Left Right
-- Without the explicit type here, psc throws:
-- Error in declaration renderYaml
-- Error in expression Presentable.ViewParser.parse(v):
-- Duplicate label "err" in row.
grrinference :: forall e. Foreign -> Eff (err :: Exception | e) Unit
-- with the explicit type, psc throws:
-- Error in declaration renderYaml
-- Cannot unify ( | e10478) with ( | e10503)
grrinference v = parse v r >>= render
in case yamlToForeign yaml of
Right v -> grrinference v
Left err -> throw $ "Yaml view failed to parse : " ++ err
I've twisted my brain, but I don't see how to unify the types here. All was well on the earlier version of PureScript. But in 0.6 I'm stuck.
--
Details on Parse
parse :: forall a p e. Foreign -> Registry a p e-> Eff (err :: Exception | e) [Presentable a p e]
More type info
type Yaml = String
type Registry a p e = M.Map String (Linker a p e)
type Attributes a = Maybe { | a}
type Parent p = Maybe { | p}
type Linker a p e = Parent p -> Attributes a -> Eff e (Parent p)
data Presentable a p e = Presentable (Linker a p e) (Attributes a) (Maybe [Presentable a p e])