我有一个由两个别名组成的数据类:String
and [String]
,即[Char]
and [[Char]]
。目前它派生Eq
和Show
:
data BashVar = BashString String | BashArray [String] deriving (Eq,Show)
为什么它不能派生自[_]
或无论如何调用通用列表类型?
我只想能够在类的实例上使用列表函数,特别是length
.
列表没有类。 length
简单定义为:
length :: [a] -> Int
不是(我想你想象的):
class ListLike l where
length :: l a -> Int
最接近列表的类可能是Foldable
:http: //hackage.haskell.org/packages/archive/base/latest/doc/html/Data-Foldable.html 但这并没有定义length
,只是各种折叠。
除此之外,如果有一个列表类,它可能仍然允许内部类型变化,就像我上面的例子一样。您的BashVar
类不允许列表中的任何类型,它固定为字符串列表。因此,即使ListLike
存在,您也无法支持它(Foldable
出于同样的原因,您也无法派生)。
两者都是类型类,而同时Eq
是数据类型。如果您查看 的类型,则为 ,而为。不同之处在于第一个具有类型类约束,而第二个根本不依赖于类型类约束,仅依赖于数据类型。不幸的是,没有办法使默认值适用于自定义数据类型。Show
[]
(==)
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]
很容易发现您正在尝试“跳跃”该语言,而无需花费最少的时间阅读甚至最基本的教程。
至少熟悉“Learn You a Haskell”的“Types and Typeclasses”一章应该可以消除您在这里提出的所有问题。否则根本不可能解释事情,因为该语言及其大多数概念与您可能试图在其上投射的任何 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
因此,这两种情况实际上在含义上非常不同。那是你要的吗?这不是一个非常类似于列表的行为。查看列表数据类型和长度函数的实现,如果您想更深入地了解这一点: 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”或类似的名称,因为“length”已经在列表中定义,并且 Haskell 中的函数重载通过类型类工作。列表类型,至少在 Haskell 98 中,是一种数据类型,而不是可以在自己的数据类型“BashVar”中实现其功能的类型类。为了规避这个限制,如果您想阅读更多信息,还有比将列表类型包装在您自己的数据类型中更多的技巧: http ://www.haskell.org/haskellwiki/List_instance