Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/visual-studio-2010/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 自由单子的可视化_Haskell_Monads_Free Monad - Fatal编程技术网

Haskell 自由单子的可视化

Haskell 自由单子的可视化,haskell,monads,free-monad,Haskell,Monads,Free Monad,我想我大致知道什么是免费单子,但我想有一个更好的方式来形象化它 自由岩浆只是二叉树,这是有道理的,因为它尽可能地“通用”,而不会丢失任何信息 类似地,自由幺半群只是列表也是有道理的,因为操作顺序并不重要。现在“二叉树”中有一个冗余,所以如果有意义的话,你可以把它展平 出于类似的原因,自由群体看起来有点像分形,这是有道理的: 为了得到其他组,我们只需将组中的不同元素识别为“相同”,就可以得到其他组 我应该如何想象自由单子?现在,我认为它是你能想象到的最通用的抽象语法树。本质上是这样吗?还是我过于简

我想我大致知道什么是免费单子,但我想有一个更好的方式来形象化它

自由岩浆只是二叉树,这是有道理的,因为它尽可能地“通用”,而不会丢失任何信息

类似地,自由幺半群只是列表也是有道理的,因为操作顺序并不重要。现在“二叉树”中有一个冗余,所以如果有意义的话,你可以把它展平

出于类似的原因,自由群体看起来有点像分形,这是有道理的: 为了得到其他组,我们只需将组中的不同元素识别为“相同”,就可以得到其他组

我应该如何想象自由单子?现在,我认为它是你能想象到的最通用的抽象语法树。本质上是这样吗?还是我过于简单化了

同样,从一个自由单子到一个列表或其他单子,我们会损失什么?我们认为什么是“相同的”

我感谢所有能说明这一点的评论。谢谢

现在,我认为[自由单子]是你能想象到的最通用的抽象语法树。本质上是这样吗?还是我过于简单化了

你太简单化了:

  • “Free monad”是“特定函子上的Free monad”或
    Free fa
    数据类型的缩写,实际上,对于
    f
    的每个选择,它都是不同的Free monad
  • 并没有一个总的结构是所有自由单子都有的。其结构分为:
    • Free
      本身贡献了什么
    • f
  • 但是让我们采取不同的方法。我学习自由单子的方法是首先研究密切相关的单子,它有一个更统一、更容易可视化的结构。我强烈建议您从链接本身进行研究

    定义操作monad的最简单方法如下:

    {-# LANGUAGE GADTs #-}
    
    data Program instr a where
      Return :: a -> Program instr a
      Bind :: instr x                  -- an "instruction" with result type `x`
           -> (x -> Program instr a)   -- function that computes rest of program
           -> Program instr a          -- a program with result type `a`
    
    …其中,
    instr
    type参数表示monad的“指令”类型,通常是GADT。例如(摘自链接):

    因此,一个
    程序
    在操作单子中,非正式地说,我将其视为一个指令的“动态列表”,其中执行任何指令产生的结果被用作函数的输入,该函数决定“指令列表”的“尾部”是什么。
    Bind
    构造函数将指令与“tail chooser”函数配对

    许多自由单子也可以用类似的术语可视化。你可以说,为给定的自由单子选择的函子充当它的“指令集”。但对于自由单子,“指令”的“尾部”或“子项”由
    函子本身管理。下面是一个简单的例子(摘自):

    在操作单体中,用于生成“尾部”的函数属于
    程序
    类型(在
    绑定
    构造函数中),而在自由单体中,尾部属于“指令”/
    函子
    类型。这允许自由单子的“指令”(一个正在分解的类比)有一个“尾巴”(如
    输出
    贝尔
    )、零尾巴(如
    完成
    )或多个尾巴(如果您选择的话)。或者,在另一种常见模式中,
    next
    参数可以是嵌入式函数的结果类型:

    data Terminal a next = 
        PutStrLn String next
      | GetLine (String -> next)  -- can't access the next "instruction" unless
                                  -- you supply a `String`.
    
    instance Functor Terminal where
        fmap f (PutStrLn str next) = PutStrLn str (f next)
        fmap f (GetLine g) = GetLine (fmap f g)
    
     x :: FreeA f a
     x = FreeA g [ s, t, u, v]
        where g :: b -> c -> d -> e -> a
              s :: f b
              t :: f c
              u :: f d
              v :: f e
    
    顺便说一句,我长期以来一直反对将自由单子或可操作单子称为“语法树”的人——实际使用它们需要将节点的“子节点”不透明地隐藏在函数中。你通常不能完全检查这棵“树”

    实际上,当你开始讨论它时,如何可视化一个自由单子完全取决于你用来参数化它的
    函子的结构。有些看起来像列表,有些看起来像树,还有一些看起来像“不透明的树”,函数作为节点。(有人曾经用一句话回应我的反对意见,比如“函数是一个树节点,有尽可能多的子节点和可能多的参数。”)

    你可能听说过

    Monad是内函子范畴中的幺半群

    你已经提到了幺半群只是列表。原来你在这里


    对此进行一点扩展:

    data Free f a = Pure a
                  | Free (f (Free f a))
    
    它不是一个普通的
    a
    列表,而是一个尾部被包裹在
    f
    中的列表。如果编写多个嵌套绑定的值结构,您将看到:

    pure x >>= f >>= g >>= h :: Free m a
    
    可能导致

    Free $ m1 $ Free $ m2 $ Free $ m3 $ Pure x
      where m1, m2, m3 :: a -> m a -- Some underlying functor "constructors"
    
    如果上例中的
    m
    为总和类型:

    data Sum a = Inl a | Inr a
      deriving Functor
    
    然后列表实际上是一棵树,在每个构造函数中,我们可以向左或向右分支


    你可能听说过

    Applicative是一类内函子中的幺半群

    。。。类别完全不同。在中有不同的免费应用程序编码的很好的可视化

    所以free
    Applicative
    也是一个列表。我把它想象成一个由
    fa
    值和单个函数组成的异构列表:

    data Terminal a next = 
        PutStrLn String next
      | GetLine (String -> next)  -- can't access the next "instruction" unless
                                  -- you supply a `String`.
    
    instance Functor Terminal where
        fmap f (PutStrLn str next) = PutStrLn str (f next)
        fmap f (GetLine g) = GetLine (fmap f g)
    
     x :: FreeA f a
     x = FreeA g [ s, t, u, v]
        where g :: b -> c -> d -> e -> a
              s :: f b
              t :: f c
              u :: f d
              v :: f e
    
    在这种情况下,尾部本身并不是用
    f
    包装的,而是分别用每个元素包装的。这可能有助于理解
    Applicative
    Monad
    之间的区别

    请注意,
    f
    不需要是
    函子
    就可以使
    应用(freeafa)
    ,与上面的
    Free
    单子相反


    还有免费的
    Functor

    data Coyoneda f a = Coyoneda :: (b -> a) -> f b -> Coyoneda f a  
    
    这使得任何
    *->*
    类型
    函子
    。将其与上面的免费
    Applicative
    进行比较。 在应用案例中,我们有一个长度n为
    fa
    值的异构列表,以及一个组合它们的n元函数。 Coyoneda是上述的一元特例


    我们可以将
    Coyoneda
    Free
    结合起来,使
    可操作
    免费单子。正如其他答案所提到的,一棵树是可以想象的,因为它涉及到一些功能。