Haskell 什么时候变态的合成是变态?

Haskell 什么时候变态的合成是变态?,haskell,functional-programming,composition,fold,catamorphism,Haskell,Functional Programming,Composition,Fold,Catamorphism,第3页,共页: 一般来说,在合成下,反同构是封闭的,这是不正确的 在什么条件下,变态构成变态?更具体地说(假设我正确理解了陈述): 假设我有两个基本函子F和G,每个函子都有折叠:foldF::(fa->a)->(μF->a)和foldG::(ga->a)->(μG->a) 现在假设我有两个代数a::FμG->μG和b::gx->X 作文的时间是什么时候。(foldfa)::μF->X一个亚同态 编辑:根据dblhelix的扩展答案,我有一个猜测:那是outG。a::FμG->GμG必须是某些自

第3页,共页:

一般来说,在合成下,反同构是封闭的,这是不正确的

在什么条件下,变态构成变态?更具体地说(假设我正确理解了陈述):

假设我有两个基本函子
F
G
,每个函子都有折叠:
foldF::(fa->a)->(μF->a)
foldG::(ga->a)->(μG->a)

现在假设我有两个代数
a::FμG->μG
b::gx->X

作文的时间是什么时候。(foldfa)::μF->X一个亚同态


编辑:根据dblhelix的扩展答案,我有一个猜测:那是
outG。a::FμG->GμG
必须是某些自然转化的
μG
处的成分
η::F a->G a
。我不知道这是否正确。(编辑2:正如科拉指出的,这是足够的,但不是必需的。)


编辑3:哈斯凯尔咖啡馆的雷恩·桑顿补充道:“如果你拥有正确的分配属性(如科拉所建议的那样)但是,拥有正确的分配性属性通常相当于某种适当相关范畴中的自然转换;因此,这只是将问题推迟到适当相关范畴是否始终存在,以及我们是否能够将“适当相关”的内容形式化“意思。”

反同构将数据结构反构造为结果值。因此,一般来说,当应用一个反同构时,结果是完全不同的,并且不能对其应用另一个反同构

例如,对
[Int]
的所有元素求和的函数是一个反同构,但结果是
Int
。无法对其应用另一个反同构


但是,一些特殊的反同构会创建与输入类型相同的结果。其中一个例子是
map f
(对于某些给定函数
f
)。在反构造原始结构的同时,它还会创建一个新的列表作为其结果。(实际上,
map f
既可以被视为反同构,也可以被视为一个映射。)因此,如果你有这样一类特殊的变体,你就可以组成它们。

如果我们考虑语义对等,两个变体的组成是一个变质现象,第一个是HyLopistic:

cata1 . hylo1 = cata2
例如(哈斯克尔):

什么时候是构图(fold2g)。(fold1f)::μF1->A变形

当存在一个
F1
-代数
h::F1 A->A
时,使得
fold1h=fold2g.fold1f

<> P>在构造学中,一般认为,不定形是不封闭的,考虑以下类型的不动点,代数,和变质作用的一般定义:

newtype Fix f = In {out :: f (Fix f)}

type Algebra f a = f a -> a

cata :: Functor f => Algebra f a -> Fix f -> a
cata phi = phi . fmap (cata phi) . out
为了合成拟同构,我们需要

algcomp ::  Algebra f (Fix g) -> Algebra g a -> Algebra f a
现在试着编写这个函数。它接受两个函数作为参数(分别属于
f(fixg)->fixg
ga->a
类型)而一个类型为
fa
的值,它需要产生一个类型为
a
的值。你会怎么做?要产生一个类型为
a
的值,你唯一的希望就是应用类型为
ga->a
的函数,但是我们被卡住了:我们没有办法把类型为
fa
的值变成类型为
ga
是吗

我不确定这对你的目的是否有用,但一个可以组合成反同构的条件的例子是,如果我们有一个从第二个反同构的结果到第二个函子的不动点的态射:

algcomp' :: (Functor f, Functor g) =>
            (a -> Fix g) -> Algebra f (Fix g) -> Algebra g a -> Algebra f a
algcomp' h phi phi' = cata phi' . phi . fmap h
(免责声明:这超出了我的专业范围。我相信我是正确的(在不同的地方提供了警告),但是…请自己验证。)

一个反同构可以被认为是一个用其他函数替换数据类型构造函数的函数

(在本例中,我将使用以下数据类型:

data [a] = [] | a : [a]

data BinTree a = Leaf a | Branch (BinTree a) (BinTree a)

data Nat = Zero | Succ Nat
)

例如:

length :: [a] -> Nat
length = catamorphism
     []   -> 0
     (_:) -> (1+)
double . length . map f = catamorphism
     []   -> Zero
     (a:) -> Succ . Succ

double . binTreeRightDepth = catamorphism
     Leaf a -> Zero
     Branch -> \a b -> Succ (Succ b)
(遗憾的是,
cataophrism{..}
语法在Haskell中是不可用的(我在Pola中看到了类似的东西)。我一直想为它编写一个准语言。)

那么,什么是
长度[1,2,3]

length [1,2,3]
length (1 : 2 : 3 : [])
length (1:  2:  3:  [])
        1+ (1+ (1+ (0 )))
        3
也就是说,出于稍后将变得显而易见的原因,最好将其定义为微不足道的等价物:

length :: [a] -> Nat
length = catamorphism
     []   -> Zero
     (_:) -> Succ

让我们再考虑几个例子:< /P>

map :: (a -> b) -> [a] -> b
map f = catamorphism
     []   -> []
     (a:) -> (f a :)

binTreeDepth :: Tree a -> Nat
binTreeDepth = catamorphism
     Leaf _ -> 0
     Branch -> \a b -> 1 + max a b

binTreeRightDepth :: Tree a -> Nat
binTreeRightDepth = catamorphism
     Leaf _ -> 0
     Branch -> \a b -> 1 + b

binTreeLeaves :: Tree a -> Nat
binTreeLeaves = catamorphism
     Leaf _ ->  1
     Branch -> (+)

double :: Nat -> Nat
double = catamorphism
     Succ -> Succ . Succ
     Zero -> Zero
其中许多可以很好地组合成新的反射。例如:

length :: [a] -> Nat
length = catamorphism
     []   -> 0
     (_:) -> (1+)
double . length . map f = catamorphism
     []   -> Zero
     (a:) -> Succ . Succ

double . binTreeRightDepth = catamorphism
     Leaf a -> Zero
     Branch -> \a b -> Succ (Succ b)
double.binTreeDepth
也有效,但从某种意义上说,这几乎是一个奇迹

double . binTreeDepth = catamorphism
     Leaf a -> Zero
     Branch -> \a b -> Succ (Succ (max a b))
这仅仅是因为
double
分布在
max
上,这纯粹是巧合。(double.binTreeLeaves也是如此)如果我们用一些不太适合加倍的东西取代
max
,那么,让我们给自己定义一个新朋友吧(这和其他的不太好)。对于不分布的
double
二进制运算符,我们将使用
(*)

让我们试着建立两个自同态的充分条件。显然,任何自同态都可以用
length
double
mapf
组合,因为它们在不查看子结果的情况下生成数据结构。例如,在
length
的情况下,您可以将
Succ
Zero
替换为你想要的任何东西,你就有了新的亚同态

  • 如果第一个反同构生成一个数据结构而不考虑其子对象的情况,那么两个反同构将组合成一个反同构。
  • 除此之外,事情变得更加复杂。让我们区分普通构造函数参数和“递归参数”(我们将用%号标记)。因此
    Leaf a
    没有递归参数,但是
                   a               |            b            |     cata(b.a)
    ===============================|=========================|================
           F a %b %c .. -> Z       |      Z -> G a b ..      |      True
    
                   a               |            b            |     cata(b.a)
    ===============================|=========================|=================
       F a %b %c .. -> H %c %d ..  |   H %a %b -> G a b ..   |       True
    
                   a               |            b            |     cata(b.a)
    ===============================|=========================|=================
     F a %b %c .. -> A (f %b %c..) |     A %a -> B (g %a)    |    Implied by g
                                   |                         | distributes over f