如何演示函子的 MAP 方法关联属性



我读到函子的映射是可关联的,它暗示了以下内容:

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

上面的方程式不应该这样写来证明关联性吗?

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

(但这是不可能的,因为函数没有map方法)。

这里有些东西我没有领会。

这是Haskell中的一个例子
您可以创建两个函数。第一个CCD_ 1,它将首先组成fg,然后应用映射函数

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中的一个示例:
创建两个函数plusOneplusTwo

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

创建一个compose函数,该函数由两个函数组成

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

创建实用程序函数composeAndMap0

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));

最新更新