数据结构分化,直觉建构

dsg*_*dsg 17 haskell algebraic-data-types data-structures

根据这篇论文,差异化对数据结构起作用.

根据这个答案:

区分,数据类型D的导数(给定为D')是具有单个"洞"的D结构的类型,即,不包含任何数据的区别位置.这令人惊讶地满足了与微积分差异相同的规则.

规则是:

 1 = 0
 X? = 1
 (F + G)? = F' + G?
 (F • G)? = F • G? + F? • G
 (F ? G)? = (F? ? G) • G?
Run Code Online (Sandbox Code Playgroud)

参考文章对我来说有点过于复杂以获得直觉.这在实践中意味着什么?一个具体的例子太棒了.

小智 20

什么是X中X的单孔上下文?没有选择:它是( - ),可以用单位类型表示.

什么是X*X中X的单孔上下文?它类似于( - ,x2)或(x1, - ),所以它可以用X + X表示(或者2*X,如果你愿意的话).

什么是X*X*X中X的单孔上下文?它类似于( - ,x2,x3)或(x1, - ,x3)或(x1,x2, - ),可由X*X + X*X + X*X表示,或(3*X ^ 2,如果你喜欢).

更一般地,具有孔的F*G是具有孔和G完整的F,或者是完整的F和具有孔的G.

递归数据类型通常被定义为多项式的固定点.

data Tree = Leaf | Node Tree Tree
Run Code Online (Sandbox Code Playgroud)

真的是说Tree = 1 + Tree*Tree.区分多项式告诉你直接子树的上下文:叶子中没有子树; 在节点中,它左边是洞,右边是树,左边是树,右边是洞.

data Tree' = NodeLeft () Tree | NodeRight Tree ()
Run Code Online (Sandbox Code Playgroud)

这是多项式的区分和渲染类型.因此,树中子树的上下文是那些树的步骤的列表.

type TreeCtxt = [Tree']
type TreeZipper = (Tree, TreeCtxt)
Run Code Online (Sandbox Code Playgroud)

这里,例如,是一个函数(未尝试的代码),它在树中搜索通过给定测试子树的子树.

search :: (Tree -> Bool) -> Tree -> [TreeZipper]
search p t = go (t, []) where
  go :: TreeZipper -> [TreeZipper]
  go z = here z ++ below z
  here :: TreeZipper -> [TreeZipper]
  here z@(t, _) | p t       = [z]
                | otherwise = []
  below (Leaf,     _)  = []
  below (Node l r, cs) = go (l, NodeLeft () r : cs) ++ go (r, NodeRight l () : cs)
Run Code Online (Sandbox Code Playgroud)

"下面"的作用是产生与给定树相关的树的居民.

区分数据类型是使"搜索"等程序通用的好方法.


ken*_*ytm 11

我的解释是,T的导数(拉链)是类似于T的"形状"的所有实例的类型,但正好用1个元素替换为"洞".

例如,列表

List t = 1     []
       + t     [a]
       + t^2   [a,b]
       + t^3   [a,b,c]
       + t^4   [a,b,c,d]
       + ...   [a,b,c,d,...]
Run Code Online (Sandbox Code Playgroud)

如果我们用洞(代表@)代替'a','b','c'等中的任何一个,我们就会得到

List' t = 0      empty list doesn't have hole
        + 1      [@]
        + 2*t    [@,b]     or [a,@]
        + 3*t^2  [@,b,c]   or [a,@,c]   or [a,b,@]
        + 4*t^3  [@,b,c,d] or [a,@,c,d] or [a,b,@,d] or [a,b,c,@]
        + ...
Run Code Online (Sandbox Code Playgroud)

另一个例子,二叉树

data Tree t = TEmpty | TNode t (Tree t) (Tree t)
-- Tree t = 1 + t (Tree t)^2
Run Code Online (Sandbox Code Playgroud)

所以添加一个洞会产生类型:

{-

Tree' t = 0                    empty tree doesn't have hole
        + (Tree X)^2           the root is a hole, followed by 2 normal trees
        + t*(Tree' t)*(Tree t) the left tree has a hole, the right is normal
        + t*(Tree t)*(Tree' t) the left tree is normal, the right has a hole

          @    or      x     or     x    
         / \          / \          / \   
        a   b       @?   b        a   @?
       /\   /\     / \   /\      /\   /\ 
      c  d e  f   @? @? e  f    c  d @? @?
-}

data Tree' t = THit (Tree t) (Tree t)
             | TLeft t (Tree' t) (Tree t)
             | TRight t (Tree t) (Tree' t)
Run Code Online (Sandbox Code Playgroud)

说明链规则的第三个例子是玫瑰树(可变树):

data Rose t = RNode t [Rose t]
-- R t = t*List(R t)
Run Code Online (Sandbox Code Playgroud)

衍生品说R' t = List(R t) + t * List'(R t) * R' t,这意味着

{-

R' t = List (R t)        the root is a hole
     + t                 we have a normal root node,
       * List' (R t)       and a list that has a hole,
       * R' t              and we put a holed rose tree at the list's hole

        x
        |
       [a,b,c,...,p,@?,r,...]
                    |
                   [@?,...]

-}

data Rose' t = RHit [Rose t] | RChild t (List' (Rose t)) (Rose' t)
Run Code Online (Sandbox Code Playgroud)

请注意data List' t = LHit [t] | LTail t (List' t).

(这些可能与拉链是"方向"列表的传统类型不同,但它们是同构的.)


导数是记录如何编码结构中位置的系统方法,例如我们可以搜索:(未完全优化)

locateL :: (t -> Bool) -> [t] -> Maybe (t, List' t)
locateL _ [] = Nothing
locateL f (x:xs) | f x       = Just (x, LHit xs)
                 | otherwise = do
                                  (el, ctx) <- locateL f xs
                                  return (el, LTail x ctx)

locateR :: (t -> Bool) -> Rose t -> Maybe (t, Rose' t)
locateR f (RNode a child)
      | f a       = Just (a, RHit child)
      | otherwise = do 
                      (whichChild, listCtx) <- locateL (isJust . locateR f) child
                      (el, ctx) <- locateR f whichChild
                      return (el, RChild a listCtx ctx)
Run Code Online (Sandbox Code Playgroud)

并使用上下文信息mutate(插入漏洞):

updateL :: t -> List' t -> [t]
updateL x (LHit xs) = x:xs
updateL x (LTail a ctx) = a : updateL x ctx

updateR :: t -> Rose' t -> Rose t
updateR x (RHit child) = RNode x child
updateR x (RChild a listCtx ctx) = RNode a (updateL (updateR x ctx) listCtx)
Run Code Online (Sandbox Code Playgroud)