Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.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 了解如何构建GHC.Generics Rep';s并转换回值_Haskell_Generics_Ghc_Ghc Generics - Fatal编程技术网

Haskell 了解如何构建GHC.Generics Rep';s并转换回值

Haskell 了解如何构建GHC.Generics Rep';s并转换回值,haskell,generics,ghc,ghc-generics,Haskell,Generics,Ghc,Ghc Generics,我正在努力学习如何使用。一个引人入胜但令人畏惧的话题 在阅读博客条目时,我学会了如何获取一个值并导航其Rep。好的 然而,读了一篇博客文章,其中描述了构建Rep并将其转换回一个值的类似过程,我被难住了。我已经通读了,但没有多大帮助 在博客条目中有以下代码。首先,构造Rep: class Functor f => Mk rep f | rep -> f where mk :: f (rep a) instance Mk (K1 i c) ((->) c) where m

我正在努力学习如何使用。一个引人入胜但令人畏惧的话题

在阅读博客条目时,我学会了如何获取一个值并导航其
Rep
。好的

然而,读了一篇博客文章,其中描述了构建
Rep
并将其转换回一个值的类似过程,我被难住了。我已经通读了,但没有多大帮助

在博客条目中有以下代码。首先,构造
Rep

class Functor f => Mk rep f | rep -> f where
  mk :: f (rep a)

instance Mk (K1 i c) ((->) c) where
  mk = \x -> K1 x

instance (Mk l fl, Mk r fr) => Mk (l :*: r) (Compose fl fr) where
  mk = Compose (fmap (\l -> fmap (\r -> l :*: r) mk) mk)

instance (Mk f f') => Mk (M1 i c f) f' where
  mk = M1 <$> mk
然后处理类型歧义:

type family Returns (f :: *) :: * where
  Returns (a -> b) = Returns b
  Returns r = r

make :: forall b f z. (Generic (Returns b), Apply f (Returns b) b, Mk (Rep (Returns b)) f) => b
make = apply (fmap (to :: Rep (Returns b) z -> (Returns b)) (mk :: f (Rep (Returns b) z)))

真的,我一开始就被困在类
Mk
中,
Mk
返回一个函子。我的问题是:

  • 什么是
    mk
    返回?为什么它是函子?对其结果的解释是什么?我可以看到
    Mk
    k1ic
    实例返回一个函数(我知道这是一个函子),它接受一个值并将其包装在
    K1
    中,但是
    Mk
    对于
    Mk(l::::r)
    Mk(M1 I c f)
    我完全不知道

  • 我猜
    Compose
    来自
    Data.Functor.Compose
    ,这意味着当我执行
    fmap fx
    时,它会执行
    fmap
    两个层次的组合函子。但是我无法理解
    Compose
    中嵌套的
    fmap
    s

  • 对于
    M1 i c f
    的例子,我认为它只会将内部值包装在
    M1
    中,因此需要
    M1 mk
    fmap M1 mk
    对我来说毫无意义

  • 显然,我没有探究这些实例的意图或意义,也没有探究这些实例如何交互来创建最终的
    Rep
    。我希望有人能给我一些启发,并在此过程中为如何使用
    GHC.Generics
    提供一个很好的解释

  • 什么是
    mk
    返回
  • 让我们先看一下GHC.Generics文档中一个更简单的例子。为了实现一个泛型函数
    encode::generic a=>a->[Bool]
    该函数将具有泛型实例的每个数据类型进行位序列化,他们定义了下面的类型类:

    class Encode' rep where
      encode' :: rep p -> [Bool]
    
    通过为每个Rep类型(M1、K1等)定义
    Encode'
    实例,他们使函数在每个数据类型上都通用

    在中,作者的最终目标是一个泛型函数
    make::generic a=>TypeOfConstructor a
    ,因此可以天真地定义:

    class Mk rep where
      mk :: (? -> p) -- what should '?' be?
    
    很快就意识到这是不可能的,因为有几个问题:

  • ->
    ,haskell中的函数类型一次只接受一个参数,因此如果构造函数接受多个参数,
    mk
    将无法返回任何合理的结果
  • 参数的数量和类型尚不清楚:它与所关注的
    rep
    类型有关
  • 结果类型不能是普通的
    p
    。没有
    rep
    上下文,就不可能派生
    :*:
    :+:
    的实例,并且该函数将不再适用于任何嵌套数据类型
  • 问题1可以通过Data.Functor.Compose解决。类型为
    A->b->c
    的函数可以编码为
    Compose((>)A)((>)b)c
    ,它可以进一步组合,同时保留大量关于参数类型的信息。通过使其成为
    Mk
    的类型参数,问题2也得以解决:

    class Functor f => Mk rep f | rep -> f where
      mk :: f (rep p)
    
    其中,
    f
    是对
    组合f g
    (>)a
    的泛化,其中包含用于构造
    rep p
    的类型级信息,即
    a->b->c->中最终
    ->
    之前的所有内容…->rep p

  • 我猜
    Compose
    来自
    Data.Functor.Compose
    ,这意味着当我执行
    fmap fx
    时,它会执行
    fmap
    两个层次的组合函子。但是我无法理解
    Compose
    中嵌套的
    fmap
    s
    :*:
    Mk
    实例中:

    instance (Mk l fl, Mk r fr) => Mk (l :*: r) (Compose fl fr) where
      mk = Compose (fmap (\l -> fmap (\r -> l :*: r) mk) mk)
    
    fmap
    仅更改嵌套组合的最内部类型,在这种情况下更改n元函数的最终结果
    mk
    这里是字面上连接两个参数列表
    fl
    fr
    ,将它们的结果放入一个产品类型,即

    f :: Compose ((->) a) ((->) b) (f r)
    g :: Compose ((->) c) ((->) d) (g r)
    mk f g :: Compose (Compose ((->) a) ((->) b)) (Compose ((->) c) ((->) d)) ((:*:) f g r)
    
    -- or unwrapped and simplified
    (a -> b -> r) -> (c -> d -> r') -> a -> b -> c -> d -> (r, r')
    
  • 对于
    M1 i c f
    的例子,我认为它只会将内部值包装在
    M1
    中,因此需要
    M1 mk
    fmap M1 mk
    对我来说毫无意义

  • 它只将内部值包装在
    M1
    中,但不清楚底层
    f
    的参数列表有多长。如果它接受一个参数,那么
    mk
    是一个函数,否则它是一个组合
    fmap
    包装了两者的最内在价值。

    注意,这里有两个独立的设计“目标”(可以这么说)——一般地派生一个函数,并使该函数“很好”。作者想写一个多元函数,比如
    a->b->…->R
    而不是
    Mk
    类生成的
    Compose
    链:
    Compose((>)a)(Compose((>)b)…R
    。如果您试图理解泛型,我认为您可以忽略除
    Mk
    类以外的所有内容,它是泛型的主要工具。我不知道作者为什么选择使用Compose编写所有内容,然后将其“转换”为多变量函数。
    f :: Compose ((->) a) ((->) b) (f r)
    g :: Compose ((->) c) ((->) d) (g r)
    mk f g :: Compose (Compose ((->) a) ((->) b)) (Compose ((->) c) ((->) d)) ((:*:) f g r)
    
    -- or unwrapped and simplified
    (a -> b -> r) -> (c -> d -> r') -> a -> b -> c -> d -> (r, r')