繁体   English   中英

从数据类中的List派生长度函数

[英]Deriving length function from List in data class

我有一个包含两个别名的数据类: String[String] ,即[Char][[Char]] 目前它派生EqShow

data BashVar = BashString String | BashArray [String] deriving (Eq,Show)

为什么它不能也从[_]派生出来,或者为什么却调用了通用列表类型?

我只希望能够在类的实例上使用列表函数,特别是length

列表没有类别。 length简单定义为:

length :: [a] -> Int

不(正如我想像的那样):

class ListLike l where
  length :: l a -> Int

列表中最接近的类可能是Foldablehttp : //hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Foldable.html但这并没有定义length ,只是各种折叠。

除此之外,如果有一个列表类,它可能仍将允许内部类型变化,如上面的示例所示。 您的BashVar类不允许列表中使用任何类型,而是固定为String列表。 因此,即使存在ListLike ,您也无法支持它(并且出于相同的原因也无法派生Foldable )。

EqShow都是类型类 ,而[]数据类型 如果查看(==)的类型,则为Eq a => a -> a -> Bool ,而length[a] -> Int 不同之处在于,第一个具有类型分类约束Eq a ,而第二个则完全不依赖于类型分类约束,仅依赖于数据类型[a] 不幸的是,无法使默认length与自定义数据类型一起使用。

最好的选择是定义自己的功能:

bashLength :: BashVar -> Int
bashLength (BashString s) = length s
bashLength (BashArray xs) = length xs

从您的问题和评论中,您在说些废话,如下所示:

  • I have a data class
  • Why can't it derive also from [_] or however the generic list type is called?
  • BashVar is an instance of [a]

可以很容易地发现您正在尝试“跳动”该语言,而无需花费最少的时间来阅读最基本的教程。

至少让您熟悉“了解Haskell”的“类型和类型分类”一章 ,才能消除您在此处提出的所有问题。 否则就不可能对其他事物进行解释,因为该语言及其大多数概念与您可能尝试在其上进行投影的任何OOP语言都相去甚远。

那么您的数据类型可以是字符串数组还是单个字符串? 您希望长度函数返回什么? 如果你这样做

bashLength :: BashVar -> Int
bashLength (BashString s) = length s
bashLength (BashArray xs) = length xs

您将获得字符串的长度:

Main> bashLength (BashString "hello")
5

或数组的长度:

Main> bashLength (BashArray ["1","2","3"])
3

因此,这两种情况实际上在含义上有很大不同。 那是你要的吗? 这不是一种列表式的行为。 如果您想进一步研究list数据类型和length函数的实现,请访问http : //www.haskell.org/onlinereport/standard-prelude.html

如果只希望您的类型表现得完全像字符串列表,则可以使用类型同义词,并免费获得列表类型的所有功能:

type BashVar = [String]

或者您可以尝试使用递归数据类型,以与定义列表类型相同的方式来模仿列表行为:

data BashVar = BashString String | BashArray [BashVar] deriving (Show)

现在,我将使bashLength仅返回数组的长度-但我不确定这是否是您要表达的内容:

bashLength :: Num a => BashVar -> a
bashLength (BashString s) = 1
bashLength (BashArray xs) = sum (map bashLength xs)

让我们尝试一下:

Main> bashLength(BashArray [])
0
Main> bashLength(BashArray [BashString "b",BashString "c"])
2

不过,如果使用这种方法,则必须将函数命名为“ bashLength”或类似名称,因为“长度”已在列表中定义,并且Haskell中的函数重载通过类型类进行。 至少在Haskell 98中,列表类型是数据类型,而不是类型类,您可以在自己的数据类型“ BashVar”中实现其功能。 为了避免这种限制,如果您想了解更多信息,除了将列表类型包装在自己的数据类型中还有更多技巧: http : //www.haskell.org/haskellwiki/List_instance

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM