Haskell Data.List.Class和语法 [英] Haskell Data.List.Class and syntax

查看:62
本文介绍了Haskell Data.List.Class和语法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试读取Haskell包Data.List.Class的源代码. (清单-0.4.2).但是我对某些语法感到困惑.

I am trying to read the source code for the Haskell package Data.List.Class. (List-0.4.2). But I am stuck with some of the syntax.

在开头,它显示为:

data ListItem l a =
    Nil |
    Cons { headL :: a, tailL :: l a }

我对第三行的语法不熟悉.我猜这最后一行等效于Cons a (l a) ??.但我不确定.我注意到该文件的标题为:{-# LANGUAGE FlexibleContexts, TypeFamilies #-}.

I am not familiar with the syntax of the 3rd line. I guess that this last line is equivalent to Cons a (l a) ??. But I am not really sure. I noticed that the header of the file says: {-# LANGUAGE FlexibleContexts, TypeFamilies #-}.

然后,随着我的前进,type语句有一个奇怪的用法:type ItemM l :: * -> *,我听不懂.

Then as I go on, there is a strange use of the type statement: type ItemM l :: * -> *, which I couldn't understand.

Data.List.Class
-- | A class for list types. Every list has an underlying monad.
class (MonadPlus l, Monad (ItemM l)) => List l where
    type ItemM l :: * -> *
    runList :: l a -> ItemM l (ListItem l a)
    joinL :: ItemM l (l a) -> l a
    cons :: a -> l a -> l a
    cons = mplus . return

任何人都可以帮助解释这些含义吗?我对Data.List有一个很好的了解,但是这种类型类的东西对我来说还不是很清楚. 我还搜索了有关使用Data.List.{Class,Tree}的Wiki,示例和/或教程,但是似乎没有任何内容,除了代码附带的注释.这里有指针吗?

Can anyone help explain what these mean? I have a perfect understanding of Data.List, but this type class thing is not really clear to me. Also I searched about wiki's, examples, and/or tutorials for using Data.List.{Class,Tree}, but there does not seem to be any, except the comments that come with the code. Any pointers here?

谢谢.

-更新- 第一个答案(@Chris)帮助我理解了Kind签名和记录语法,这确实很有帮助.但是,就如何捕获/定义List的行为以及它为熟悉的Data.List定义添加什么值而言,我仍然无法从总体上理解这部分代码.这里有一些进一步的细节,其中只有两个实例语句. Identity术语也来自import Data.Functor.Identity (Identity(..)).您能帮我们解释一下这是什么类型类,以捕获我们通常所知道的列表的特征吗?再次,我在线搜索了它,但是除了代码本身之外,实际上没有关于Data.List.Class的文档.有人知道吗?

-- update -- The first answer (@Chris) helped me understand the Kind signature and the Record Syntax, which is really helpful. However, I still cannot make sense out of that piece of code overall in terms of how it captures/defines the behavior of a List and what value it adds to the familiar Data.List definitions. Here are some further details, where there are only two instance statements. Also the Identity term comes from import Data.Functor.Identity (Identity(..)). Can you please help explain what this is type class do to capture the characteristics of a list as we normally know it? Again, I searched it online but there is really no documentation for Data.List.Class except the code itself. Anyone knows?

此外,在typeclass约束中还有另一个使用type语句的示例,与本示例中的示例类似吗?我搜索了learningyouahaskell.com/(@Landei),但找不到这样的例子.我假设这里type的用法类似于您在C ++模板中使用typedef来定义类型上的函数"的方式,对吧?

Also, is there another example use of the type statement in the typeclass constraint similar to what's in this example? I searched learnyouahaskell.com/ (@Landei) but couldn't find such an example. I am assuming that the usage of type here is similar to how you would use typedef's in C++ templates to define 'functions on types', right?

再次感谢.

instance List [] where
    type ItemM [] = Identity
    runList [] = Identity Nil
    runList (x:xs) = Identity $ Cons x xs
    joinL = runIdentity
    cons = (:)

instance Functor m => Functor (ListItem m) where
    fmap _ Nil = Nil
    fmap func (Cons x xs) = Cons (func x) (fmap func xs)

推荐答案

记录语法

data ListItem l a = Nil | Cons { headL :: a, tailL :: l a }

被称为记录语法.您猜对的结构与您键入的结构相同时是正确的

is called record syntax. You're correct when you guess that the structure is the same as if you'd typed

data ListItem l a = Nil | Cons a (l a)

但是,您还获得了两个访问器功能:

However, you also get the two accessor functions:

headL :: ListItem l a -> a
headL (Cons a _) = a

tailL :: ListItem l a -> l a
tailL (Cons _ as) = as

记录语法是语法糖-在这里,您可以节省大约4行代码.您可以按照常规方式进行模式匹配,如本段正上方的代码所示,也可以在模式匹配中使用记录语法:

Record syntax is syntactic sugar - here it saves you around 4 lines of code. You can pattern match in the normal way, as in the code directly above this paragraph, or you can use the record syntax in the pattern match:

safeHeadL :: ListItem l a -> Maybe a
safeHeadL Nil                = Nothing
safeHeadL (Cons {headL = a}) = Just a

同样,将其转换为标准模式匹配.

Again, this is desugared into standard pattern matching.

class (MonadPlus l, Monad (ItemM l)) => List l where
  type ItemM l :: * -> *
  runList :: l a -> ItemM l (ListItem l a)
  joinL   :: ItemM l (l a) -> l a

  cons :: a -> l a -> l a
  cons = mplus . return

type family 声明.线

  type ItemM l :: * -> *

种类签名.当我们说某物具有种类*时,是指它是基本类型,例如IntFloat.说某物具有* -> *种类意味着它是类型构造函数,即,它接受一个类型并返回另一个类型.

is a kind signature. When we say something has kind *, we mean that it's a base type, like Int or Float. To say that something has kind * -> * means that it is a type constructor, i.e. it takes a type and returns another type.

Maybe类型的构造函数具有这种签名:

The Maybe type constructor has this kind signature:

Maybe :: * -> *

请记住,Maybe本身不是类型.必须给它一个类型,然后返回一个类型.给它Int,您会得到Maybe Int.给它Double,您会得到Maybe Double.

Remember that Maybe on its own isn't a type. It has to be given a type, and then it returns a type. Give it Int and you get Maybe Int. Give it Double and you get Maybe Double.

类型构造器ItemM l接受类型参数(类型为*)并返回类型为*的东西.请注意,由于l*类型,因此您拥有

The type constructor ItemM l takes a type parameter (of kind *) and returns something of kind *. Note that since l is of kind *, you have

ItemM :: * -> * -> *

ItemM接受两种类型,并返回一个类型(等效地,它接受一种类型,并返回一元类型的构造函数).

i.e. ItemM takes two types, and returns a type (equivalently, it takes one type and returns a unary type constructor).

通过在类中包括类型声明,您施加了以下约束:在所有类实例中,ItemM l中的l必须与List l中的l相匹配.无法创建不匹配的类的实例.

By including the type declaration in the class, you impose the constraint that in all instances of the class, the l in ItemM l has to match up with the l in List l. It's impossible to create an instance of the class where these don't match up.

这篇关于Haskell Data.List.Class和语法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆