【问题标题】:Understanding the type signature of gfoldl from Data.Data.Data从 Data.Data.Data 了解 gfoldl 的类型签名
【发布时间】:2015-03-18 20:06:15
【问题描述】:

Data定义为其核心功能之一gfoldl

gfoldl
  :: (Data a)
  => (forall d b. Data d => c (d -> b) -> d -> c b) 
  -> (forall g. g -> c g)   
  -> a  
  -> c a

里面cc (d -> b)的作用是什么?为什么它不只是一个普通的折叠,比如

gfoldl'
  :: (Data a)
  => (forall d. Data d => r -> d -> r)
  -> r
  -> a  
  -> r

【问题讨论】:

    标签: haskell types type-signature scrap-your-boilerplate


    【解决方案1】:

    这个想法是 Haskell 中代数数据类型的值具有以下形式

    C x_1 x_2 ... x_n
    

    其中C 是构造函数,x_i 是参数。什么

    gfoldl app con
    

    就是把这样的值变成

    con C `app` x_1 `app` x_2 ... `app` x_n
    

    从而将a 变成c a。假设C 的类型是

    C :: T_1 -> T_2 -> ... -> T_n -> D
    

    那么我们来看看中间表达式的类型:

    con C                                   :: c (T_1 -> T_2 -> ... -> T_n -> D)
    con C `app` x_1                         :: c (T_2 -> ... -> T_n -> D)
    con C `app` x_1 `app` x_2               :: c (... -> T_n -> D)
    con C `app` x_1 `app` x_2 ... `app` x_n :: c D
    

    c 上的参数化允许所有这些中间类型 不同的。如果我们改用 gfoldl' 之类的简单折叠,那么所有 这些中间类型必须相同。

    gfoldl 的动机是成为一名 单一概括,可让您表达 SYB 函数 gmapQgmapT(以及其他一些函数)。 gmapQgmapT 的类型是:

    gmapQ :: Data a => (forall d. Data d => d -> u) -> a -> [u]
    gmapT :: Data a => (forall b. Data b => b -> b) -> a -> a
    

    虽然gmapQa 折叠成us 的统一列表并且可以 使用gfoldl' 表示,这对于gmapT 是不可能的。

    但是,使用gfoldl,我们可以使用c = Identity 使我们能够获得 类似gmapTc = Const 得到类似gmapQ 的东西。

    更多细节,你可能还想看看论文Scrap your boilerplate Reloaded,它表明gfoldl是一个普通的(然而 在该论文中称为Spine 的数据类型的高阶)折叠。

    使用恒等函子来获得变换和 从单个底层表示更新行为有一些 类似于从“van Laarhoven”镜头获得镜头操作的方式。

    【讨论】:

    • c 上的参数化允许所有这些中间类型不同”——你能详细说明一下吗?这并没有明显的意义。
    • @leftaroundabout 在gfoldl' 中,所有c X 的出现都是r,即它们都必须是相同的类型。使用c X,我仍然可以让它们都属于同一类型,例如Const r X,它与r 同构。但我也可以让它们都不同,例如在Identity X 中,它与X 同构。
    猜你喜欢
    • 2014-04-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多