Ошибка типа Sanctuary.Js с функтором Identity

1

Я играю вокруг следующих уроков теории Bartosz Milewski на youtube. Он описывает функторы Const и Identity, поскольку "базовые" функторы могут быть получены из (вероятно, либерального перефразирования с моей стороны).

Моя проблема, внедрив ES6+/fantasy-land (не важная) версия функтора, появляется, когда я начинаю интегрироваться с библиотекой 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)
}

Вот несколько простых применений (поскольку я также работал с линзами, получающими ион)

// 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 работает немного лучше (нет 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});

или заменить святилище рамдой. Так что это похоже на некоторую проблему согласованности типов с функцией отображения идентификационной информации.

Вопрос в том, как мне заставить все эти части играть вместе в стиле счастливого рода.

  • 0
    Я заметил, что extractFrom , кажется, не определен. Это просто foo => foo.extract() ?
  • 0
    Извините - возможно, я пропустил это. но да, по сути это (fl послушный).
Показать ещё 4 комментария
Теги:
functional-programming
sanctuary
ramda.js
fantasyland

1 ответ

0
Лучший ответ

Вам нужно будет определить конструктор типа для вашего типа (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, Z относится к классам type святилища, а type относится к идентификаторам type святилища.

  • 0
    Для моего образования, почему это не проблема для функтора Const? И вообще, когда вам нужно добавлять определения типов в типы и функции, а когда нет?
  • 0
    Среда требуется для разрешения переменных типа в сигнатурах полиморфных функций. Рассмотрим S.concat :: Semigroup a => a -> a -> a . Учитывая S.concat (x) (y) Sanctuary должен сначала определить все типы, членом которых является x . Затем он должен отфильтровать этот набор, включив в него только типы, членом которых также является y . Если результирующий набор является пустым набором, проверка типа не выполняется. Таким образом, SI (Identity (42)) не сможет проверить тип, если Identity (42) не является членом какого-либо типа в среде.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню