Hello, everyone! thx for the adding to the group!
Is there some “isomorphic” tool, way to transpiler PureScript <=> Haskell both sides ?
Hello, everyone! thx for the adding to the group!
Is there some “isomorphic” tool, way to transpiler PureScript <=> Haskell both sides ?
I don’t think so. There’s a few issues between the two languages as well:
Offtopic, but related: I was thinking about implementing a transpiler from Elm to PureScript and transpile all existing packages. I think in this direction, it might work, since everything that can be expressed in Elm can be expressed in PS. I didn’t start the project though, because while it would be fun to develop, I don’t think the result is very helpful and there would be a lot of users interested in actually using it.
I think the idea is not that bad (I surely have some use cases) but I guess you’d have to have the elm-runtime in there too, plus the stuff for ports so this might be quite some work
Yes, I see. It could not be possible then to identify the expressions where Haskell use thunks for implementing its lazy evaluation and translate them into the equivalent strict expressions in Purescript?. In this case, it could be feasiblein theory to do a homomorphic transformation and to yield a version of the haskell code that behaves in the same well as the original, by preserving the structure and behavior of the original code. (?).
greetings.
Well that translation is not obvious to me. After all you can express more with non-strict evaluation strategies.
If you want it to behave the same you’d need the same lazy runtime simulated IMO and then it’s probably easier to wait/use GHCjs or the webassambly backend of GHC
Thx for the reply
Let me show a little example to understand the matter better.
For instance lets say that we have such a haskell snippet:
Blockquote
add x y = if x <= 0
then x + y
else let x’ = x - 1
in add x’ (y + 1)
So far I understand if x is greater than 0, it performs the computation x’ = x -1 and creates a thunk for the expression add x’(y+1) , right? this thunk should be stored in memory and evaluated later on when the result is needed.
OK, then we can convert the expression in the haskell function to Purescript without thunks as it follows:
Blockquote
add x y = if x <= 0
then x + y
else let x’ = x - 1
y’ = y + 1
in add x’ y’
It is clear now that unlike the haskell code there are not thunks stored in the memory. Instead the intermediate values x’ and y’ are calculated inmediately. That means so far I understood that the code willl be evaluated strictly and will not delay any calculations yielding the same result.
Is it all this stuff right? could it be extended to deal with other expressions?
Well not exactly:
add x y =
if x <= 0
then x + y
else
let x’ = x - 1
in add x’ (y + 1)
it depends how you use it - if you just do let x = add 4 5
and let’s assume x
is not pruned (used somewhere) than x
itself will point to a / be a thunk.
Now let’s say you evaluate that somewhere along the line (let’s say in GHCi by doing x
- this will print
the value so it does call show
on it and prints it - this usually will fully evaluate … well usually).
Then something along the lines of what you describes happens: it needs to evaluate the first if
for that it needs to evaluate the x
there - so your 4
gets evaluated (well it’s a value anyway) and the if evaluates to the else
- there x
will be a thunk at first and it returns add ´x
(y+1)` (y+1 will be a thunk also), and so on.
See that’s the point: it’s almost impossible to tell when a thunk will get evaluated as this is driven by need/runtime - my hunch is that a static check to this would be equivalent to the halting problem (so unsolvable)
Yes you can often translate into strict evaluation but the behaviour will change and some tricks like this:
or True _ = True
or False x = x
> or True undefined ... evals to True
will be nasty to handle (and those tricks are everywhere in Haskell and they are used!)
Thank you for the thoroughness of your reply.
Thinking about the problem of evaluating or simulating in Purescript the behavior of the run-time thunks in Haskell, I wonder if it could be feasible to implement that in Purescript with monads/profunctors which effectively delay the execution of the computations according with the context of the monade/profunctor
Following with the former example. To circumvent the problem of the undefined/error avoiding by the lazy but not the strict evaluation one can maybe try something like this with the Eff monad:
Blockquote :
orTrue :: Boolean → Boolean → Boolean
orTrue = \a1 a2 → if a1 == true then true else a2
or :: Boolean → Boolean → Eff (console :: CONSOLE) Boolean
or = \a1 a2 → if a1 == true then return true else return a2
or True _ would evaluate to True. The _ in this context
would be equivalent to undefined, but since the first argument is True, the function returns True regardless of the value of the second argument .
Now applying the same solution in the case of the infinite loop/recursion:
Blockquote :
– Import the Eff monad, which provides a way to execute computations with side effects
import Control.Monad.Eff
– Define a type alias for the Context monad:
type Context a = forall r. (Int → Eff r a) → Eff r a
– Define theadd
function, which takes two argumentsx
andy
and returns aContext Int
value
add :: Int → Int → Context Int
add x y =
– Use theif
statement to check the value ofx
if x <= 0
– Ifx
is less than or equal to 0, returnx + y
as the result
then \k → k (x + y)
– Ifx
is greater than 0, continue the computation
else \k →
– Bind the result ofadd (x - 1) (y + 1)
to a new valuex'
let x’ = add (x - 1) (y + 1)
– Passx'
to the continuationk
in x’ k
– Define therunContext
function, which takes aContext a
value and returns anEff r a
value
runContext :: Context a → Eff r a
runContext c = c id
IMHO it seems to be feasible with the help of the Eff monad to solve the problem of converting the Haskell expression into the “strict” Purescript.
It might be quite interesting to create a (simple, limited in scope) implementation of a PureScript → Haskell compiler just to see how performance would be compared to running PureScript on NodeJS, or the pscpp (compiling to C++) or psgo (compiling to go) backends. The amount of translation that needs to happen is probably much less when going to another functional language (especially when forcing Haskell into Strict mode in the compiled modules) vs. an imperative/class-oriented language like C++.
Off topic, not what you’re asking for, but Haskell types can be converted to PureScript types with GitHub - eskimor/purescript-bridge: Create PureScript datatypes from Haskell datatypes