1

I am using "Ramda/Fantasy" library for creating Monads. And i am trying to combine IO's to get element from the DOM and change its text content. But the problem is that function that changes content of the element needs to take two arguments element, and text that we want to set. I don't know how I can that efficiently I found one solution that looks like this:

const getElement = id => IO(() => document.querySelector(id));
const setElementText = element => text => IO(() => element.textcontent = text);

getElement('h1').map(setElementText).runIO()('New Title').runIO();

Is there a better way?

Hitmands
  • 13,491
  • 4
  • 34
  • 69
Djordje Vuckovic
  • 383
  • 1
  • 5
  • 11
  • 1
    [Please do not upload images of code/errors when asking a question.](https://meta.stackoverflow.com/questions/285551/why-not-upload-images-of-code-errors-when-asking-a-question) – VLAZ Jan 31 '22 at 07:29

2 Answers2

3

Two small changes to help with your example:

  • Swapping the order of the arguments to setElementText allows you to partially apply the text value.
  • Using chain rather than map remove the need for the second runIO call.
const getElement = id => IO(() => document.querySelector(id))
const setElementText = text => element => IO(() => element.textContent = text)

getElement('h1').chain(setElementText('New Title')).runIO()
Scott Christopher
  • 6,458
  • 23
  • 26
  • Ty that solution works, I also found a second solution using a "ap()" method, but I don't know is it okay to call "runIO()" twice? – Djordje Vuckovic Jan 31 '22 at 09:38
  • 1
    Calling `runIO` twice is not necessarily wrong, though typically not necessary, as you "break out" of the IO type when you do. For applications making heavy use of an IO-like type, they will typically be comprised of many IO types combined together and then a single call to `runIO` with the IO value at the entry-point of the application. – Scott Christopher Jan 31 '22 at 10:54
0

I also found a second solution to use "ap()" method which applies the function (resulting from the action in this IO instance) to the value resulting from the action in the given IO instance.

import {IO} from "ramda-fantasy";

const getElement = id => IO(() => document.querySelector(id))
const setElementText = element => text => IO(() => element.textContent = text)

const someText = IO(() => 'New Title')

const setHeading = getElement('h1').map(setElementText).ap(someText).runIO();
setHeading.runIO(); // It works
Djordje Vuckovic
  • 383
  • 1
  • 5
  • 11