Haskell中map、filter与fork相关等式验证:找出错误等式
以下是对6个Haskell等式逐一验证的结果:
等式1:
map f . take n = take n . map f
成立。无论f是何种函数、n取何值,先取列表前n个元素再映射,与先映射整个列表再取前n个元素的结果完全一致。
示例:令f = (+1),n=2,列表[1,2,3]
左边:map (+1) (take 2 [1,2,3]) = [2,3]
右边:take 2 (map (+1) [1,2,3]) = [2,3]等式2:
map f . reverse = reverse . map f
成立。反转列表后映射,等价于先映射整个列表再反转,映射操作不改变元素的相对顺序反转结果。
示例:令f = (*2),列表[1,2,3]
左边:map (*2) (reverse [1,2,3]) = [6,4,2]
右边:reverse (map (*2) [1,2,3]) = [6,4,2]等式3:
map f . sort = sort . map f
不成立。只有当f是单调函数时等式才成立,若f不单调,会破坏排序后的元素顺序。
示例:令f = (mod2),列表[3,1,2]
左边:map (mod2) (sort [3,1,2]) = map (mod2) [1,2,3] = [1,0,1]
右边:sort (map (mod2) [3,1,2]) = sort [1,1,0] = [0,1,1]
左右结果明显不同,等式不成立。等式4:
map f . filter p = map fst . filter snd . map (fork (f,p))
成立。这里fork (f,p)表示将元素x转换为元组(f x, p x):左边先过滤出满足p的元素再映射f;右边先给每个元素生成(f x, p x)元组,过滤出snd为真(即p x为真)的元组,再取fst部分,两者结果一致。
示例:令f = (+1),p = even,列表[1,2,3,4]
左边:map (+1) (filter even [1,2,3,4]) = [3,5]
右边:map fst (filter snd (map (\x -> (x+1, even x)) [1,2,3,4])) = map fst [(3,True),(5,True)] = [3,5]等式5:
reverse . concat = concat . reverse . map reverse
成立。左边先拼接所有子列表再整体反转;右边先反转每个子列表,再反转子列表的顺序,最后拼接,两者结果等价。
示例:子列表[[1,2],[3,4]]
左边:reverse (concat [[1,2],[3,4]]) = reverse [1,2,3,4] = [4,3,2,1]
右边:concat (reverse (map reverse [[1,2],[3,4]])) = concat (reverse [[2,1],[4,3]]) = concat [[4,3],[2,1]] = [4,3,2,1]等式6:
filter p . concat = concat . map (filter p)
成立。左边先拼接所有子列表再过滤满足p的元素;右边先过滤每个子列表中满足p的元素再拼接,结果完全相同。
示例:令p = odd,子列表[[1,2],[3,4]]
左边:filter odd (concat [[1,2],[3,4]]) = [1,3]
右边:concat (map (filter odd) [[1,2],[3,4]]) = concat [[1],[3]] = [1,3]
内容的提问来源于stack exchange,提问作者Aditya Bansal

