我有一个由两个别名组成的数据类:String
和[String]
,即[Char]
和[[Char]]
。目前,它派生Eq
和Show
:
data BashVar = BashString String | BashArray [String] deriving (Eq,Show)
为什么它也不能从[_]
派生出来,或者是否会调用泛型列表类型?
我只是希望能够在类的实例上使用列表函数,特别是length
。
答案 0 :(得分:8)
列表没有课程。 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
类不允许列表中的任何类型,它已修复为String列表。因此,即使存在ListLike
,也无法支持它(并且出于同样的原因,您无法导出Foldable
。)
答案 1 :(得分:3)
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
答案 2 :(得分:1)
从你的问题和评论中,你可以说出如下的废话:
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]
很容易发现你试图“跳”语言而不花费最少的时间阅读最基本的教程。
让自己至少熟悉“了解你的哈斯克尔”的"Types and Typeclasses" chapter应该删除你在这里提出的所有问题。否则就不可能解释其他事情,因为语言及其大部分概念与您尝试在其上投射的任何OOP语言有太大的不同。
答案 3 :(得分:1)
那么您的数据类型可以是字符串数组还是单个字符串?你希望你的长度函数返回什么? 如果你这样做
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”或类似的东西,因为“length”已在列表中定义,而Haskell中的函数重载通过类型类工作。列表类型,至少在Haskell 98中,是一种数据类型,而不是类型类,其功能可以在您自己的datataype“BashVar”中实现。 为了避免这种限制,除了在您自己的数据类型中包装列表类型之外,还有更多技巧,以防您想要阅读更多内容: http://www.haskell.org/haskellwiki/List_instance