crockjs和apply函数需要一个函数作为值

时间:2018-07-26 05:50:25

标签: javascript functional-programming

我实际上是在学习函数式编程,并且正在尝试学习和使用crockjs

目前,我正在尝试实现https://fsharpforfunandprofit.com/monadster/中描述的“ monadster”程序。

这就是我现在所拥有的(只是开始...)

const State = require("crocks/State");

const LivingPart = (unitOfForce, deadThing) => ({ unitOfForce, deadThing });

// Creating the potential living thing
const makeLiveThingM = deadThing => {
  const becomeAlive = vitalForce => {
    const unitOfForce = 1;
    const remaining = vitalForce - unitOfForce;

    return { part: LivingPart(unitOfForce, deadThing), remaining };
  };

  return State.get(becomeAlive);
};

// Using containers
const deadLegM = makeLiveThingM("deadLeg");
const deadArmM = makeLiveThingM("deadArm");

const livingThings = deadLegM.ap(deadArmM).evalWith(1);

console.log(livingThings);

我的问题是它引发了以下错误:

/Users/pc/Soft/experiments/functional/crocks/node_modules/crocks/State/index.js:101
        throw new TypeError('State.ap: Source value must be a function')
        ^

TypeError: State.ap: Source value must be a function

据我所知,这可能是因为我不了解apply函数或State.get的运行方式。对我来说,它在我的代码中接受一个函数作为其内部值,但事实并非如此。

有人可以解释一下,告诉我我在做什么错吗?

感谢您的帮助

1 个答案:

答案 0 :(得分:2)

欢迎使用JS中的函数式编程,并感谢您给crocks一炮打响。

在看那篇文章时,需要注意的事情之一是作者在介绍State ADT内部机制的工作原理,而不是实际上如何使用现有的State ADT。

我将提供有关如何手动处理State事务的说明,这与您在实现中的情况很接近。然后,我将给出一个简短的示例,说明如何使用构造助手(例如getmodify来递减VitalForce)来处理和构建State事务

我还将简要介绍如何使用Applicative

因此,让我们从crocks引入几个ADT

const Pair = require('crocks/Pair')
const State = require('crocks/State')

我们需要State构造函数接受一个函数,该函数将返回Pair(作者在文章中提及的元组)。 here可以找到构造函数的工作原理。

在讨论State函数之前,我们需要LivingPart函数:

// LivingPart :: (Integer, String) -> Object
const LivingPart = (unitOfForce, part) =>
  ({ [part]: { unitOfForce } })

我已经更改了您原来的结构,因此我们可以将任何给定的Part与另一个合并。

现在有了混合功能,我们就可以实现makeLiveThing。您在实现中几乎拥有它。唯一真正的区别是我们需要使用函数构造State ADT并返回Pair。注意,我们仍然引入String,但返回State ADT,该ADT将在调用runWith时执行。请记住,当前状态将传递到State实例包装的函数中(在这种情况下,vitalForce是我们的状态):

// makeLiveThing :: String -> State Integer Object
const makeLiveThing = part => State(
  vitalForce => {
    const unitOfForce = 1
    const remaining = vitalForce - unitOfForce

    return Pair(
      LivingPart(unitOfForce, part),
      remaining
    )
  }
)

现在我们有了创建LivingPart并处理状态交易(递减1)的方法,我们可以创建几个部分:

// rightLeg :: State Integer Object
const rightLeg =
  makeLiveThing('right-leg')

// leftArm :: State Integer Object
const leftArm =
  makeLiveThing('left-arm')

现在是加入这些State实例的任务。您认为使用apply是正确的,因为当ADT同时具有ap方法和of方法时,它就称为Applicative。当我们有一个Applicative时,我们可以认为该类型能够合并(2)个独立的实例,这些实例不依赖于另一个实例的结果。我们只需要提供一种告诉类型如何组合的方法即可。

通常使用可以对ADT中包含的类型起作用的函数来完成。在我们的例子中,它是Object,因此组合(2)对象的一种方法是使用Object.assigncrocks提供了一个名为assign的帮助程序,它可以做到这一点,所以请带它进入:

const assign = require('crocks/helpers/assign')

现在我们有了一种组合内部值的方法,我们需要将此函数“提升”为我们的State类型,crocks还有一个可以在{{1}上使用的函数}来提升并应用称为Applicative的ADT(2)实例的内部值。意思是“将一个函数提升为带有两个实例的应用程序”

因此,我们也将其引入,然后创建一个用于连接(2)liftA2的函数:

Parts

现在,使用此功能,我们可以抬起并连接这些部分,并使用我们的const liftA2 = require('crocks/helpers/liftA2') // joinParts :: Applicative m => m Object -> m Object -> m Object const joinParts = liftA2(assign) 运行结果:

VitalForce

请注意,结果的结果在左边(组合的活动部分),结果在右边(其余的joinParts(rightLeg, leftArm) .runWith(10) //=> Pair( { left-arm: { unitOfForce: 1 }, right-leg: { unitOfForce: 1 } }, 8 ) )。

以下是上述内容的参考:

现在,我将展示一个简短的示例,说明如何设置单个VitalForce事务以从池中提取State。我不会在这里详细解释,但是您应该能够在此示例与VitalForce文档之间收集一些信息:

State

以下是包含这些功能的一些文档:

因此,作为旁注,我进行了LiveCode广播on this channel,我将翻阅此博客文章,并讨论如何在const State = require('crocks/State') const constant = require('crocks/combinators/constant') const mapProps = require('crocks/helpers/mapProps') const { modify } = State // decrementBy :: Integer -> Integer -> Integer const decrementBy = x => y => y - x // VitalForce :: { units: Integer } // decUnitsBy :: Integer -> VitalForce -> VitalForce const decUnitsBy = units => mapProps({ units: decrementBy(units) }) // getVitalForce :: Integer -> State VitalForce VitalForce const getVitalForce = units => modify(decUnitsBy(units)) .map(constant({ units })) getVitalForce(3) .runWith({ units: 10 }) //=> Pair( { units: 3 }, { units: 7 } ) 中实现这一点,如果您愿意的话。感兴趣。

希望这会有所帮助!