How to evaluate an Eff monad in psci? - purescript

I'm learning Purescript using the purescript-node-http library. If I have a value whose type is the following:
> :t f
forall t3.
Eff
( http :: HTTP
, console :: CONSOLE
| t3
)
Request
How would I be able to evaluate this in psci and assign the Request return value to a variable?

You can't bind the result to a variable right now. That feature might be supported in a later version. Note that you can evaluate the result and print it out.
If you use the browser as your evaluation environment (with --port) then one option is to store the result in a Ref and use the Ref later to retrieve the value.
The problem with the Node backend is that there is no persistent state, so that approach would not be possible at all with the Node backend.

Related

Is it possible to run something in Eff in a halogen ComponentHTML funcion?

There are a couple of bindings to moment.js I'd like to use for rendering time spans in my Halogen UI which have types something like
diffMins :: forall eff. Moment -> Moment -> Eff (now :: NOW | eff) Number
If I want to use this function in my UI like this:
H.span_ [H.text $ diffMins (fromEpoch_ 0) (fromEpoch_ myTimeStamp)]
But this is in Eff so I can't.
What I can do is call into moment with this function:
js:
exports.duration_ = function (millis) {
return moment.duration(millis).humanize();
};
ps:
foreign import duration_ :: Number -> String
humanizeMilliseconds :: Milliseconds -> String
humanizeMilliseconds (Milliseconds n) = duration_ n
My question (or several) then:
Is it "cheating" to call into javascript without saying it's an Eff. If not when is it considered ok and when not? I could squit either way and see these functions as side effecting or not.
If I couldn't have changed the way I'm calling moment, or indeed it is a bad idea, is there a way to do this in HTML?
It is indeed not possible to perform anything effectful during renders in Halogen, as HTML is only data and render is state -> HTML.
As Phil says in the comment, you don't have to use Eff in the signature of FFI functions though, if you're sure they perform no effects. In this case, it's probably safe, since it's basically arithmetic on dates - but there may be some locale-specific stuff going on? If so it's only a little bit dodgy, as at least it will always give the same result on the same machine, unless the OS clock is messed with. I'd be a little hesitant to accept that as being effect free, but if it was really a problem and I needed to do it I'd at least ensure the function is not exported so it can't be used anywhere else except in the exceptional circumstance.
You could just do this in the component eval somewhere though and store the value in the component state - myTimeStamp must already be in there, so you could compute this value at the same time? That way you're not recomputing a static value with each render too.

For this function, what does "return Left" mean in the case of IO?

In Database.MongoDB.Query, there is this function:
access :: MonadIO m => Pipe -> AccessMode -> Database -> Action m a -> m a
The documentation says this about the function:
Run action against database on server at other end of pipe. Use access mode for any reads and writes. Return Left on connection failure or read/write failure.
What does "return Left" mean here? I ask because m can be any monad (with a MonadIO instance). For instance, what does "return Left" mean if m is just the IO monad?
Must m be the Either monad for me to be able to detect connection or read/write failure when using the access method?
Yes. It's a type. Return Left comes from an older version. If any errors happens then it just throws IO exceptions. We'll need to fix it.
I filed a bug for it. https://github.com/mongodb-haskell/mongodb/issues/67

Mutating state in Purescript

I am just starting to learn Purescript so I hope that this is not a stupid question.
Suppose that we have an object
a = {x:1,y:2}
an we want to change x to equal 2. As far as I can see if we use the ST monad we will have to copy the whole object in order to change the value. If the initial object is big this would be very inefficient. What is the right way to mutate objects in place?
The ST monad is a fine approach, but depending on your use case, there may or may not be standard library functions for this.
The Data.StrMap module in purescript-maps defines a foreign type for homogeneous records with string keys, so if your values all have the same type, you could use Data.StrMap.ST to mutate your record in place.
If not, you should be easily able to define a function to update a record in place using ST and the FFI. The tricky bit is picking the right type. If you want to do something for a specific key, you could write a function
setFoo :: forall r a h eff. STRef h { foo :: a | r } -> a -> Eff (st :: ST h | eff) Unit
for example. Defining a generic setter would be more difficult without losing type safety. This is the trade-off made by Data.StrMap: you restrict yourself to a single value type, but get to use arbitrary keys.

How do you use the class method for Data.Function.Memoize?

I am working on an NP search problem and was told I can speed up the search process by using said package. Since memoisation is a new concept to me, I find it hard to wrap my head around anything other than the 'standard' memoised Fibonacci sequence.
In order to instantiate a data type 'a' as Memoizable I need to define a function memoize (:: (a-> v) -> a -> v) on it.
I have a Datatype data Formula which is in the classes (Eq, Ord, Show). I will have to define my own instance declaration, but don't know what function is expected.
What exactly is this function supposed to define for memoisation to work? The package description doesn't elaborate on this, and I doubt function application (which fits the type signature) will speed anything up.
You should read about typeclasses. Here is how I understand the package.
The following definition is given:
class Memoizable a where
memoize ∷ (a → v) → a → v
You should think of the memoize function as something like:
memoize :: (Memoize a) => (a → v) → a → v
Ie: you can apply it to a function from a to v iif an instance of Memoize a is declared. The package declare instances for some basic types like Int
So if you wish to memoize compute :: Int -> WidgetData, you shoud use memoize compute which has the same type without doing anything.
If you wish to memoize a function which takes as input a type without a Memoize instance, you will have to declare it yourself. More likely, you should rely on the template functions like deriveMemoizable to do that for you:
{-# LANGUAGE TemplateHaskell #-} -- put this at the top
deriveMemoizable ''T
I doubt function application (which fits the type signature) will
speed anything up.
It depends of the problem at hands. If compute is expensive, and you call it twice with the same input, it will store the results and avoid computing them twice. If it is not the case, you will increase the memory usage of your program without any gain.

How do I use postgresqlConnect in the Database.HaskellDB.HDBC.PostgreSQL module?

I am not quite sure how to use the postgresqlConnect function in module Database.HaskellDB.HDBC.PostgreSQL to connect to a PostgreSQL database. The Haddock documentation page only states the type signature:
postgresqlConnect :: MonadIO m => [(String, String)] -> (Database -> m a) -> m a
What is a supposed to be?
How do I connect to a PostgreSQL server with postgresqlConnect?
This is what I guess: The first parameter is a list of options, if you have no specific options, just pass []. The next parameter is the code you actually want to run with the database. You get a Database argument and can do any monadic stuff with it. The postgresqlConnect function evaluates this monadic action, disconnects the databse and returns the result of it - m a. Most time you probably want to use IO a though.