Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

A neat little function request #10

Open
brakubraku opened this issue Jul 23, 2024 · 8 comments
Open

A neat little function request #10

brakubraku opened this issue Jul 23, 2024 · 8 comments

Comments

@brakubraku
Copy link

Hi,

same as there is

run :: JSM () -> IO ()

would you mind adding a function like

runWithResult :: JSM a -> IO a

I would like to use it to make entropy package compile for WASM by using javascript to generate random numbers.

@amesgen
Copy link
Owner

amesgen commented Jul 23, 2024

Thanks for the issue!

Replied in tweag/ghc-wasm-miso-examples#17 (comment) regarding getting entropy to compile.

In general, the relatively heavyweight run :: JSM () -> IO () function is intended to be invoked only once in order to start your application, which can then work entirely within the JSM monad.

@brakubraku
Copy link
Author

However, let's consider a case when you depend on a package which needs to run e.g. random number generation.

I suspect there is no true randomness source on WASM, so I would like to use the one from javascript - There is JSDOM.Generated.Crypto module, however those functions run in JSM. Obviously I am not going to rewrite the whole package to entirely run in JSM monad. In order to easily modify the package, I would need something like:

runWithResult :: JSM a -> IO a

I only see very impractical ways how to solve this, unless there is such function.

Do you think it's feasible/possible to have such function?

@amesgen
Copy link
Owner

amesgen commented Aug 13, 2024

I suspect there is no true randomness source on WASM

On WASI (https://wasi.dev/), which the GHC WASM backend uses, there actually is a true randomness source. That is e.g. what is powering this PR: haskellari/splitmix#73

There is JSDOM.Generated.Crypto module, however those functions run in JSM. Obviously I am not going to rewrite the whole package to entirely run in JSM monad.

What "whole package" are you referring to here? Generally, it is expected that your entire application should run in JSM (or something stacked on top of that) when you want to use JSaddle.


You can always resort to using the WASM JS FFI directly instead of JSaddle; these functions run directly in IO, not in JSM.

A related project would be to add native WASM support to ghcjs-dom. Currently, ghcjs-dom basically conditionally reexports one of:

  • ghcjs-dom-jsffi or ghcjs-dom-javascript when using GHCJS or the new GHC JS backend.

    Here, all functions run in MonadIO.

  • ghcjs-dom-jsaddle when compiling with anything else (in particular native GHC, but also WASM GHC).

    Here, all functions run in MonadJSM (or rather MonadDOM), like the one you linked above.

It should be possible to write a ghcjs-dom-wasm package that uses the WASM JS FFI similarly (but not identically) to ghcjs-dom-jsffi/ghcjs-dom-javascript, where all functions are in MonadIO.

I also mention this here:

Skip JSaddle commands, use WASM JSFFI more directly. Not clear if this is worth the extra complexity.

@brakubraku
Copy link
Author

The package I am referring to is 'entropy'. It is a dependency of another dependency. If I was to change a function in entropy to run in JSM (for the random number generation), I would have to turn all those which depend on it to JSM as well... that's what I mean by impractical.

Looks like going either the "cbits" or "WASM JS FFI" way would be the cleanest/easiest to pull of.

Thanks!

@amesgen
Copy link
Owner

amesgen commented Aug 13, 2024

Actually, entropy shouldn't need any changes apart from the build-type: Simple change that I mentioned here: tweag/ghc-wasm-miso-examples#17 (comment)

E.g. building a simple executable depending on entropy

main = print =<< getEntropy 123

and running it via wasmtime works just fine for me. Do you get some exception?

@brakubraku
Copy link
Author

Yes I get exceptions - ensurePoolInitialized. I am running the resulting bin.wasm in firefox though

@amesgen
Copy link
Owner

amesgen commented Aug 13, 2024

Yes I get exceptions - ensurePoolInitialized. I am running the resulting bin.wasm in firefox though

Ah right, that makes sense, as openHandle tries to open /dev/urandom which doesn't necessarily exist (the same problem existed for splitmix).

Using /dev/urandom only is a fallback in case getentropy, which is used only because we disable the custom setup, which is unfortunate as WASI only supports getentropy, but not the "fallback" /dev/urandom 😄

It should be possible to adapt this though by tweaking the cbits 👍

@amesgen
Copy link
Owner

amesgen commented Aug 13, 2024

Simple implementation based on getentropy here: amesgen/entropy@f771c80 (EDIT also see haskell/entropy#86)

source-repository-package
  type: git
  location: https://github.com/amesgen/entropy
  tag: f771c8010f001b87c5ccf9b61703b6912f7062d5

This works fine both in the browser and via wasmtime for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants