我正在从头开始尝试,学习Contravariants和更深入的Sanctuary知识。代码“可以工作”,但是我的类型并不完全正确。
下面是Contravariant
const {contramap: contramapFl, extract } = require('fantasy-land');
const getInstance = (self, constructor) =>
(self instanceof constructor) ?
self :
Object.create(constructor.prototype) ;
// Contra a ~> g: a -> ?
const Contra = function(g){
const self = getInstance(this, Contra)
// :: F a ~> b -> a -> F b [ b -> a -> ? ]
self[contramapFl] = f => Contra( x => g(f(x)) )
self[extract] = g
self['@@type'] = 'fs-javascript/contra'
return Object.freeze(self)
}
// UPDATE adding type to constructor
Contra['@@type'] = 'fs-javascript/contra'
我尝试将类型设置为正确的
const $ = require('sanctuary-def');
const type = require('sanctuary-type-identifiers');
const Z = require('sanctuary-type-classes') ;
const isContra = x => type (x) === 'fs-javascript/contra'
const ContraType = $.UnaryType(
'fs-javascript/contra',
'http://example.com/fs-javascript#Contra',
isContra,
x => [x[extract]])($.Unknown)
然后我的测试
const {create, env} = require('sanctuary');
const {contramap} = create({checkTypes: true, env: env.concat(ContraType) });
const isEven = Contra(x => x % 2 === 0) ;
console.log(Z.Contravariant.test(isEven)) // => true
const isLengthEvenContra = contramap(y => y.length, isEven)
const isStringLengthEven = isLengthEvenContra[extract]
console.log(isStringLengthEven("asw")) //=> ERROR
TypeError:类型变量约束违反Contra ::Contravariant f => (b -> a) -> f a -> f b^11)“fs-javascript/ =>”::String f => (x=>g(f(X) ::Function,(c -> d) x => x%2函数0 ::===,(c -> d)由于不存在上述所有值都是其成员的类型,因此违反了类型变量约束。
如果我禁用了类型检查,那么它就会按预期工作,所以从逻辑上讲,它看起来是正确拼接在一起的。我定义了我自己的contramap版本
const def = $.create({ checkTypes: true, env: $.env.concat(ContraType) });
const contramap2 =
def('contramap2', {}, [$.Unknown, ContraType, ContraType],
(f, x) => {
const z = x[contramapFl](f)
return z
}
)
然后我重新运行测试:
const isEven = Contra(x => x % 2 === 0) ;
console.log(Z.Contravariant.test(isEven)) // => true
const isLengthEvenContra = contramap2(y => y.length, isEven)
const isStringLengthEven = isLengthEvenContra[extract]
console.log(isStringLengthEven("asw")) //=> false
因此,尽管存在关于对比函数器是否是解决此问题的最佳方法(学习练习)的讨论,但问题是,当定义我自己的逆变量实现时,我如何在启用了类型检查的中使用避难所的对比映射函数。
通过添加代码进行更新后:
Contra['@@type'] = 'fs-javascript/contra'
已将错误更改为:
TypeError:类型变量约束违反contramap ::Contravariant f => (b -> a) -> f a -> f b^1^1 1) 3 ::Number,FiniteNumber,NonZeroFiniteNumber,Integer,NonNegativeInteger,ValidNumber 2) x => x%2 === 0 ::Function,(c -> d)由于不存在上面所有值都是其成员的类型,已违反类型变量约束。
// Contra (Integer -> Boolean)
const isEven = Contra(x => x % 2 === 0) ;
// String -> Integer
const strLength = y => y.length
// I Think: Contra (String -> (Integer -> Boolean))
const isLengthEvenContra = contramap(strLength, isEven)
// (String -> (Integer -> Boolean))
const isStringLengthEven = isLengthEvenContra[extract]
我对反变量函数器的理解是,它预先组合了其中的函数,函数是通过contramap
传入的。因此,如果逆变量包含函数f
,并且它是带有g
的contramap
,它将返回一个新的包装x = g(f(x))
的逆变函数,我是否误解了这()
https://stackoverflow.com/questions/50774333
复制相似问题