Closed wcbeard closed 10 years ago
I believe what is happening is that since there is an Eff
inside of the promise, the result ends up being a function that would need to be run in order to print out the trace
messages to the console.
I don't know the best approach yet, but one way to make it work could be to introduce a function
foreign import unsafeRunEff
" function unsafeRunEff(f) {\
\ return f();\
\ } " :: forall e a. Eff e a -> a
doStuff :: forall b . Eff (trace :: Trace | b) Unit
doStuff = do
trace "Hello world 2."
trace "Hello world 3."
fff :: forall a b c. a -> Promise b (Eff (trace :: Trace | c) Unit)
fff _ = return doStuff
controller http = do
promise <- get "http://localhost:9501/examples/Todomvc/main.html" http
return $ do fa <- then' fff promise
return $ unsafeRunEff fa
I will have to think about it some more though.
If we can come up with a good way to do this, having an example would be great! Thanks!
Another option is that we could include a function:
foreign import unsafeRunPromiseEff
" function unsafeRunPromiseEff(p) {\
\ return p.then(function(eff){return eff();}); \
\ } "
:: forall e a b. Promise a (Eff e b) -> Promise a b
Using it (as in the example above) like
controller http = do
promise <- H.get "http://localhost:9501/examples/Todomvc/main.html" http
return $ unsafeRunPromiseEff $ promise >>= fff
@ethul I may be running into a situation where your first proposed function could be useful (but I'm still getting my head around how effects work in PS…). If I want to pass a function to the scope which changes the scope, it has an effect return type, which does not run when I call the function in JavaScript.
If I define function
testController' scope a = do
let x = trace "I can see this if x is returned"
extendScope {todo: "have dinner"} scope
let x' = trace "I can't see this, I guess because laziness"
x
I can attach {testControllerS: testController' scope}
in the controller. But when I call testControllerS
with ng-click like “testControllerS(’s’)”, I see nothing. If I call it with testControllerS(’s’)()
, I see the print statement and I see the scope modified accordingly.
It looks like the JavaScript creates a function that returns another function with the do
body, which additionally need an FFI step for the final call. Am I thinking about it correctly, or is there something I'm missing? (it looks like your current modification here only deals with promise effects, not executing general effects, right?)
Right. Since testControllerS
has the type Eff
, once it is compiled to Javascript, you have to run the function wrapper, which is what you're doing with testControllerS(’s’)()
. So I think you have the right idea there.
And the update to promises is specialized to effects within a promise.
I'll probably write something like what you proposed above in my file:
foreign import unsafeRunEff
" function unsafeRunEff(f) {\
\ return f();\
\ } " :: forall e a. Eff e a -> a
but do you think it would be a common enough need to include it in the repo, or is it more of an edge case (or should testControllerS(’s’)()
type JS calls be preferred in PS)?
I am thinking this might be something best left up to the developer.
For example, some might want to run the effects outside of purescript, like doing testControllerS(’s’)()
. While others might want to run them in purescript with an unsafeRunEff
function.
In the Todomvc
example, I was running effects similar to testControllerS(’s’)()
.
I'm trying to run a function with an effect while calling
>>=
(well, actuallythen'
) on an http promise, and while I can get my program to typecheck, it doesn't seem to be running as I expect.I wrap the result of my "effectful" (or whatever it's called) function
doStuff
in a promise and call itf
:Then when I call it with
then'
on the http response promise, I don't see anything printed to console:When I cheat by writing it in JS (and lying about the type...), it works fine:
Is this a bug in the Promise interface, or a bug in my thinking? Or is it intended that I write effectful Promise solutions in JS?
I'd ultimately like to try to get a working '
$http
request + bind result to scope' program working, and perhaps include it in/examples
here if you think it'd be helpful.