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

Javascript 如何使用IO monad正确创建DOM元素?,javascript,functional-programming,monads,Javascript,Functional Programming,Monads,我试图编写一个javascript代码来生成DOM元素,但要以函数的方式,因为所有函数都会产生副作用和突变。为了实现这一点,我正在使用IO monad,但我认为我仍然不知道如何很好地使用它们 首先,我使用的是crocks库,它提供了很多ADT来处理函数JS(我知道有ramda,但它们不提供Monad)。另外,我正在使用一个小模块,它允许我使用组合声明DOM元素。() 上面的代码是有效的,但显然是不纯净的。我让IO导入,但我不使用它,因为我不知道如何在不破坏代码的情况下实现它。我知道IO必须接收一

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

首先,我使用的是crocks库,它提供了很多ADT来处理函数JS(我知道有ramda,但它们不提供Monad)。另外,我正在使用一个小模块,它允许我使用组合声明DOM元素。()


上面的代码是有效的,但显然是不纯净的。我让IO导入,但我不使用它,因为我不知道如何在不破坏代码的情况下实现它。我知道IO必须接收一个函数作为参数,然后返回IO(f(x)),但我完全不知道如何对createHeader变量和appendChild实现它。此外,对于IO,当我运行createHeader变量时,它会返回一个函数,但是appendChild需要一个节点对象。

好的,所以我解决了这个问题,主要的问题是……我把一个没有副作用的函数(createHeader如果不附加到DOM中,它将什么都不会做)视为不纯函数。唉……我是新手

正如鲍勃在评论中所说,唯一不纯洁的部分是附加部分

因此,我的解决方案如下:

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

append(createHeader)
  .run();

它只在IO被“激活”后创建DOM元素,因此推迟了副作用。希望这能帮助其他新手的功能性程序员

“但它显然是不纯净的”为什么?
IO
在DOM的上下文中仅仅意味着用thunks(没有参数的函数)推迟不纯净的计算。现在您需要两件事情:您需要通过丢弃第一个计算的返回值来对不纯计算进行排序。你想通过依赖第一个的返回值来链接不纯的计算。差不多就是这样了。@Jonaswillms
appendChild
??!?请不要说创建DOM元素/子树不是不纯的,而是将它们附加到浏览器的DOM中是不纯的。所以我真的不需要在IO中包装createHeader,因为它不会直接改变DOM?这可能会让事情变得更容易…我会在这里做一些测试,记住你说的话,但更多的反馈和提示总是非常感谢!当然,
run(),因此,关于前者的推理更容易——至少当你习惯于代数代码时是如此部分已经与纯
createHeader
构造分离得很好:-)
//append might not be a good name for this action but...
const append = nodeObj => IO(() => {
  document.body.appendChild(nodeObj);
})

append(createHeader)
  .run();