javascript - 身份仿函数的 Sanctuary.Js 类型错误

标签 javascript functional-programming ramda.js fantasyland sanctuary

我正在 YouTube 上学习 Bartosz Milewski 的范畴论类(class)。他将 Const 和 Identity 仿函数描述为可以派生的“基础”仿函数(可能是我的自由派释义)。

我的问题是,在实现 ES6+/fantasy-land(不重要)版本的仿函数后,一旦我开始与 map 和管道的 Sanctuary 库集成,就会出现问题。

实现非常简单

const {map: flMap, extract } = require('fantasy-land');

const getInstance = (self, constructor) =>
    (self instanceof constructor) ?
        self :
        Object.create(constructor.prototype) ;

const Identity = function(x){
    const self = getInstance(this, Identity)

    self[flMap] = f => Identity(f(x))
    self[extract] = () => x

    return Object.freeze(self)
}

这是一些简单的用法(因为我也在使用 ionic 导出透镜)

// USAGE
const {map, pipe, curry} = require("sanctuary")

const extractFrom = x => x[extract]()

const setter = (f, x) => (pipe([
    Identity,
    map(f),
    extractFrom
])(x))

const double = x => x + x

console.log(Identity(35)) //=> 35
console.log(map(double, Identity(35))) // ERROR Should be Identity(70)
console.log(setter(double, 35)) // ERROR Should be: 70
TypeError: Type-variable constraint violation

map :: Functor f => (a -> b) -> f a -> f b
                     ^            ^
                     1            2

1)  35 :: Number, FiniteNumber, NonZeroFiniteNumber, Integer,
    NonNegativeInteger, ValidNumber

2)  () => x :: Function, (c -> d)
    f => Identity(f(x)) :: Function, (c -> d)

Since there is no type of which all the above values are members, the
type-variable constraint has been violated.

但是 Const 仿函数工作得更好一些( map 中没有调用 f)

const Const = function(x) {
    const self = getInstance(this, Const)

    self[map] = _ =>  Const(x)
    self[extract] = () => x

    return Object.freeze(self)
}

const getter = (f, x) => (pipe([
    Const,
    map(f),
    extractFrom
])(x))

console.log(getter(double, 35)) //=> 35

此外,通过删除类型检查证明一切都是“逻辑上合理的”

const {create, env} = require('sanctuary'); 
const {map, pipe, curry} = create({checkTypes: false, env: env});

或者用 ramda 替换避难所。所以它看起来像是身份映射函数的某种类型一致性问题。

问题是我如何让所有这些部分以一种快乐的方式一起发挥作用。

最佳答案

您需要为您的类型定义一个类型构造函数 (IdentityType::Type -> Type),并将 IdentityType ($.Unknown) 包含在您的 Sanctuary 中S.create中描述的环境文档。具体来说,您需要这样的东西:

//    IdentityType :: Type -> Type
const IdentityType = $.UnaryType
  ('my-package/Identity')
  ('http://example.com/my-package#Identity')
  (x => type (x) === Identity['@@type'])
  (identity => [Z.extract (identity)]);

const S = create ({
  checkTypes: process.env.NODE_ENV !== 'production',
  env: env.concat ([IdentityType ($.Unknown)]),
});

在上面的代码片段中,$ 指的是 sanctuary-def , Zsanctuary-type-classestype 指的是 sanctuary-type-identifiers .

关于javascript - 身份仿函数的 Sanctuary.Js 类型错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50745797/

相关文章:

javascript - 从子 Controller 获取表单状态到父 Controller

python - 在没有 ZIP 的情况下在 python 中成对附加

php - 为什么我的 reduce 实现的函数组合会返回一个闭包?

ramda.js - Ramda 的传感器 : Lazy one-to-many branch

javascript - Ramda - 部分应用的功能取决于完整的应用

javascript - 过滤后渲染 react 组件

javascript - 使用 css jquery 将 div 结构更改为新的 div 结构

javascript - 单击事件未触发,但鼠标悬停有效

swift - Swift 扩展中具有泛型类型参数的方法

javascript - 使用ramdajs进行迭代计算