adding to do block, stops code execution - purescript

foreign import subscribeEventedOnPrime
"function subscribeEventedOnPrime(n){ \
\ return function(fn){ \
\ return function(obj){ \
\ return function(){ \
\ obj.addEventListener(n, fn); \
\ return obj; \
\ }; \
\ }; \
\ }; \
\}" :: forall d a o eff.
String ->
(d -> a) ->
o ->
Eff (customEvent :: CustomEvent | eff) o
subscribeEventedOn n f o = subscribeEventedOnPrime n (\e -> do
trace "wtf" -- if this line is removed, everything seems to work
f $ newEvent e."type" e."detail"
) o
Whether a do block has one line vs more than one line, seems to effect whether or not that code actually gets called. What am I missing?

I think it's because by intoducing the trace you're making d -> a into something like
forall e. d -> Eff (trace :: Trace | e) Unit
which means it's not going to be evaluated unless you use unsafeInterleaveEff or something similar to actually run it.
I'm not 100% sure, but maybe the compiler shouldn't let you use the do without the trace at all, I'll have to investigate a bit.

Related

Get keyboard event in purescript

I want to get keydown event in purescript so I used DomEvent.
Here is my code.
main :: Eff (HA.HalogenEffects (console :: CONSOLE, timer :: T.TIMER)) Unit
main = HA.runHalogenAff do
body <- HA.awaitBody
cube <- runUI C.cubes unit body
documenttarget <- liftEff $ window >>= document <#> DHT.htmlDocumentToEventTarget
addEventListener (EventType "keydown") (eventListener test) true (documenttarget)
H.liftEff $ T.setInterval (1000 / frameRate) do
HA.runHalogenAff $ cube.query $ H.action C.Tick
When I try to run this code, I am getting error like this.
documenttarget <- liftEff $ window >>= document <#> DHT.htmlDocumentToEventTarget
Coudn't match type Eff with type Aff
I know aff and eff but I am new to purescript so I am not sure what I have to do to fix this issue.
What can I do?
The block that you pass to halogenRunAff is an Aff block, so every line in it must be an Aff. But liftEff returns an Eff instead. So there is a mismatch.
This is what the compiler is telling you: "can't match Eff with Aff".
To fix this, replace liftEff with liftAff:
documenttarget <- liftAff $ window >>= document <#> DHT.htmlDocumentToEventTarget

How to convert partial functions to safe(Maybe) functions?

I want it to use library-defined partialfunc more convenient, or write callback with partial pattern-matching.
like this,
partialMaybe :: forall a b. (Partial => a -> b) -> a -> Maybe b
I couldn't find similar in some major libraries.
How to define it? or already defined in libs?
data ABC a = A a | B a | C a
f1 = someHigherOrderFunc $ partialMaybe \(A a) -> someFunc a -- if not 'A', return Nothing.
-- same as
f2 = someHigherOrderFunc $ case _ of A a -> Just $ someFunc a
_ -> Nothing -- requires line break, seems syntax redundant...
using: purescript 0.11.6
Edit:
I did it...
partialMaybe :: forall a b. (Partial => a -> b) -> a -> Maybe b
partialMaybe f a = runPure $ catchException (const $ pure Nothing) (Just <<< unsafePartial f <$> pure a)
this is...umm...very ugly. it's not.
'Failed pattern match' exception is thrown by the purescript.
so I think it should be able to handle by purescript.
Can't do it?
If you want an exception if a case is missed, use Partial. If you want otherwise, use Maybe or Either or another appropriate sum type.
You can catch the exception thrown from a failed pattern match. There is no way for a failed pattern match to not throw an exception.

Resolving Effects and Maybes

spec = describe "Router" $ do
let sampleRoutes = [( Tuple "/" "views/index.yaml" ),
( Tuple "/foo" "views/foo.yaml" ),
( Tuple "/bar" "views/bar.yaml" )]
it "should default to the first of the list" $ do
r <- fst <$> head sampleRoutes
fprint r
The above throws the following error:
Error in declaration spec
Cannot unify Data.Maybe.Maybe with Control.Monad.Eff.Eff u4505.
I believe its because it is expect a second argument that is of type Eff, but because of
the use of Maybe introduced by head the second arguments ends up being of type Maybe instead.
it :: forall e a. String -> Eff e a -> Eff (it :: It | e) Unit
The problem is, I have no idea how to resolve this. Can I not have a Maybe instead an effectful block of code?
Maybe can be used in a do block, but all of the actions in the block have to be of type Maybe a for some a.
The same is true for Eff eff - you can use Eff eff with do, but all actions have to be of type Eff eff a for some a.
You can't mix and match the two types of effects within a do block.
It looks like you want to use a value of type Maybe a inside a do block whose monad is Eff eff. You have a couple of options:
Use Data.Array.Unsafe.head which will give you an unwrapped Tuple, which you can call fst on directly.
Pattern match on the Maybe value to decide the course of action in the Eff monad:
it "should default to the first of the list" $ do
case head sampleRoutes of
Nothing -> ... -- Handle empty array
Just tuple -> fprint (fst tuple) -- Print the first component
.. rest of do block ..
In this example, it's also possible to make use of traverse_ from Data.Foldable.
Since you're working with a Maybe (Tuple String String), Maybe has a Foldable instance, and Eff e has an applicative instance, you can use traverse_ rather than (<$>).
You just need to supply a function Tuple String String -> Eff e a for some a. If you compose fst and fprint, you get exactly that.
Your example becomes
spec = describe "Router" $ do
let sampleRoutes = [( Tuple "/" "views/index.yaml" ),
( Tuple "/foo" "views/foo.yaml" ),
( Tuple "/bar" "views/bar.yaml" )]
it "should default to the first of the list" $
traverse_ (fst >>> fprint) $ head sampleRoutes

haskell facebook exceptions

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

ghci displaying execution stack

So I'm working through some initial chapter exercise of Real World Haskell and I wanted to know if there is an option in GHCi to make it show function evaluation with parameters on each recursive call. So for example I wrote a simple version of 'map', and when I apply it, I would like GHCi to display each recursive call with actual arguments (and hopefully expression results). Something which allows me to follow whats going on behind the scenes.
P.S. As I write this I have a feeling it may be limited by the laziness of haskell's execution model, correct me if I'm wrong.
You can use hood for this:
import Debug.Hood.Observe
map2 f [] = []
map2 f (x:xs) = f x : (observe "map2" $ map2) f xs
main = runO $ print $ map2 (+1) ([1..10] :: [Int])
When you run it, it will print each call to map2 with the corresponding arguments and the result that was returned. You'll see something like:
.
.
.
-- map2
{ \ { \ 10 -> 11
, \ 9 -> 10
} (9 : 10 : [])
-> 10 : 11 : []
}
-- map2
{ \ { \ 10 -> 11
} (10 : [])
-> 11 : []
}
-- map2
{ \ _ [] -> []
}
For more check the examples.
I typically use Debug.Trace:
import Debug.Trace
buggy acc xs | traceShow (acc,xs) False = undefined
buggy acc [] = acc
buggy acc (x:xs) = buggy (acc + x) xs
main = print $ buggy 0 [1..10]
This lets me see how the buggy function works:
(0,[1,2,3,4,5,6,7,8,9,10])
(1,[2,3,4,5,6,7,8,9,10])
(3,[3,4,5,6,7,8,9,10])
(6,[4,5,6,7,8,9,10])
(10,[5,6,7,8,9,10])
(15,[6,7,8,9,10])
(21,[7,8,9,10])
(28,[8,9,10])
(36,[9,10])
(45,[10])
(55,[])
55
The key is having a pattern that never matches, but prints something while it's not matching. That way it always gets evaluated (and hence prints the debugging information), and it's easy to tack on to any function. But you can also make it match if you only want to see certain cases, like:
buggy acc [] = acc
buggy acc (x:xs) | traceShow (acc, x, xs) True = buggy (acc + x) xs
Then you only get debugging output at the non-base-case:
(0,1,[2,3,4,5,6,7,8,9,10])
(1,2,[3,4,5,6,7,8,9,10])
(3,3,[4,5,6,7,8,9,10])
(6,4,[5,6,7,8,9,10])
(10,5,[6,7,8,9,10])
(15,6,[7,8,9,10])
(21,7,[8,9,10])
(28,8,[9,10])
(36,9,[10])
(45,10,[])
55
YMMV.
I would recommend looking at the question How do I get a callstack in Haskell?, and Don Stewart's answer with linked guides on how to use ghci for debugging