как продемонстрировать ассоциативное свойство метода MAP функтора - PullRequest
0 голосов
/ 26 декабря 2018

Я прочитал, что карта функтора является ассоциативной и подразумевает следующее:

Functor.map(f).map(g) == Functor.map(x => g(f(x))

Разве вышеприведенное уравнение не должно быть написано так, чтобы продемонстрировать ассоциативность?

Functor.map(f).map(g) == Functor.map(f.map(g))

(но это кажется невозможным, потому что у функций нет метода карты).

Есть кое-что, чего я здесь не понимаю.

1 Ответ

0 голосов
/ 26 декабря 2018

Это пример на Хаскеле.Вы можете создать две функции.Первый composeAndMap, который сначала будет составлять f и g, а затем применить функцию карты.

composeAndMap :: Functor f => (b -> c) -> (a -> b) -> f a -> f c
composeAndMap f g = fmap (f . g)

Второй будет называться mapAndCompose, который будет составлять две частичные прикладные функции, используя функцию карты.Первая карта будет использовать f, а вторая - g следующим образом:

mapAndCompose :: Functor f => (b -> c) -> (a -> b) -> f a -> f c
mapAndCompose f g = fmap f . fmap g

В конце концов вы можете сравнить результаты каждой функции, используя конкретный экземпляр функтора, наиболее очевидныйэто функтор списка.

list :: [Int]
list = [1..5]

main :: IO ()
main = print $ mapAndCompose (+1) (+2) list == composeAndMap (+1) (+2) list

Не следует забывать и закон об идентичности.

identity :: Functor f => f a -> f a
identity = fmap id

composeAndMap :: Functor f => (b -> c) -> (a -> b) -> f a -> f c
composeAndMap f g = fmap (f . g)

mapAndCompose :: Functor f => (b -> c) -> (a -> b) -> f a -> f c
mapAndCompose f g = fmap f . fmap g

list :: [Int]
list = [1..5]

main :: IO ()
main = do 
  print $ identity list == list    
  print $ mapAndCompose (+1) (+2) list == composeAndMap (+1) (+2) list

Это пример в JavaScript:Создайте две функции plusOne и plusTwo

function plusOne(val) {
    return val + 1;
}

function plusTwo(val) {
    return val + 2;
}

Создайте compose функцию, которая состоит из двух функций

function compose(f, g) {
    return (val) => f(g(val));
}

Создайте служебную функцию sequenceEquals

function sequenceEquals(arr1, arr2) {
    for (var i = 0; i < arr1.length; i++) {
        if (arr1[i] !== arr2[i]) {
            return false;
        }
    }

    return true;        
}

Теперь вы можете сравнить две реализации:

let list = [1,2,3,4,5];
let composed = compose(plusOne, plusTwo);
let composeAndMap = list.map(composed);
let mappedTwice = list.map(plusTwo).map(plusOne);

console.log(sequenceEquals(composeAndMap, mappedTwice));

и закон идентичности.Создайте функцию идентификации:

function identity(value) { return value; } 

и сравните результаты:

console.log(sequenceEquals(list.map(identity), list));
...