javascript - 如何使用 IO monad 正确创建 DOM 元素?

标签 javascript functional-programming monads

我正在尝试编写一个生成 DOM 元素的 JavaScript 代码,但是是以函数式的方式,因为所有函数都会产生副作用和突变。为了实现这一点,我使用了 IO monad,但我想我仍然不知道如何很好地使用它们......

首先,我使用的是 crocks 库,它提供了大量 ADT 来与函数式 JS 配合使用(我知道有 ramda,但他们不提供 monad)。另外,我使用了一个小模块,它允许我使用组合来声明 DOM 元素。 (https://github.com/queckezz/elementx)

import IO from 'crocks/IO';
const { div, a, h1, h2, ul, li, button } = require('elementx');

const createHeader = div(
  h1(
    {class: 'title'},
    'This is a title'
  ),
  h2(
    {class: 'subtitle'}, 
    'This is a subtitle'
  ),
  div(
    {class: 'link'},
    a(
      {href: 'http://github.com'},
      'Github'
    )
  )
);

document.body.appendChild(createHeader);

上面的代码可以工作,但显然不纯粹。我保留了 IO 导入,但我没有使用它,因为我不知道如何在不破坏代码的情况下实现。我知道 IO 必须接收一个函数作为参数,然后它返回 IO(f(x)),但我对如何将它实现到 createHeader 变量和appendChild 感到非常困惑。此外,通过 IO,createHeader 变量在运行时返回一个函数,但appendChild 需要一个 Node 对象。

最佳答案

好吧,我解决了这个问题,主要问题是......我将一个不会产生副作用的函数(如果不附加到 DOM,createHeader 将不执行任何操作)视为不纯的。叹气……我是新手。

唯一不纯粹的部分是附加,正如 bob 在评论中所说。

所以我的解决方案如下:

//append might not be a good name for this action but...
const append = nodeObj => IO(() => {
  document.body.appendChild(nodeObj);
})

append(createHeader)
  .run();

只有在 IO 被“激活”时才会创建 DOM 元素,从而推迟了副作用。希望这可以帮助其他新手函数式程序员!

关于javascript - 如何使用 IO monad 正确创建 DOM 元素?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55358197/

相关文章:

javascript - 尝试使用 jade 渲染 html 文件,但它仍然将其定位为 jade

JavaScript 在 IE、Firefox 和 Opera 中工作正常,但在 Safari 或 Chrome 中则不然 (Textbox.value)

c# - 转换 Func<> 类型

scala - 函数式编程中改变状态

rust - 提升功能到选项

haskell - 为什么 "bind"在 Haskell Monads 中写为 >>=?

Javascript if this OR this statement - 忽略第二个条件

javascript - 了解 Redux 的基本实现 | prevState 是如何使用的?

haskell - 理解 Haskell 中的 $

javascript - 立即创建 Observable 并排队发出直到订阅