我刚刚开始在 Haskell 中定义自己的类型,我发现 http://www.haskell.org/haskellwiki/Type的第 3 节中 关于表示卡片的示例很有用。我想做一些事情,但我不知道如何实现它。我将尝试使用卡片类比进行解释。
我想使用不同的卡片集合。假设我们修复了卡总是有 CardValue 和 Suit,但除了标准系列之外,我还想允许一副有第五套“红宝石”的套牌。我希望能够做一些事情,比如采用 Kind1 和 Kind2 并定义一种卡片 Kind3,它尽可能地适合 Kind1 和 Kind2 的花色组合,以及来自 Kind1 的花色组合。我还想编写一个程序,用户可以输入花色名称等,然后我们可以用她输入的卡片类型进行一些标准的卡片操作。 我不想做的只是写出有限数量的不同数据类型,因为我事先不知道我所有不同类型的卡片会是什么。
我可以想象一个涉及大量列表和大量检查以查看事物是否是列表元素的解决方案,但我想这将是一场噩梦,而且效率非常低下。
让我编写一些不起作用的伪代码,但可能比我上面的描述更好地了解我想要做什么。
-- this isn't real code!
type Suit = [String]
type CardValue = [String]
data (Card s v) = (Card s v) {suit :: (s :: Suit), value :: (v :: CardValue)}
usualSuit :: Suit
usualSuit = ["Club","Diamond","Heart","Spade"]
flowerSuit :: Suit
flowerSuit = ["Rose","Daisy","Poppy"]
当然我知道这是胡说八道,而且我猜这违反了在编译时定义类型的原则(我可以看到这是一个很好的原则)。
谁能告诉我:
- 有没有办法像我描述的那样做?
- 有没有更好的方法来实现同样的目标?
我也对要阅读的链接/关键字感兴趣,但请注意,我不太了解编程术语,甚至不太了解 Haskell。
我确实想使用 Haskell 来做到这一点——惰性求值和无限列表对我来说非常有用,而且我已经编写了代码来做这些事情。
我试过谷歌搜索并浏览了一些 Haskell 教程(我还是个初学者!)但没有发现任何有用的东西。这可能是因为我不知道要搜索什么词。
谢谢
编辑:我担心我没有解释我想做什么。这是一些编译时没有错误的真实代码,并带有解释我希望它做什么的注释。
import Data.List
type Suit = String
type Value = Integer
type ListOfSuits = [Suit]
type ListOfValues = [Value]
data Deck = Deck {listofsuits :: ListOfSuits, listofvalues :: ListOfValues } deriving (Show)
sillyDeck :: Integer -> Deck
-- This is some function. For example, we might have
sillyDeck n = Deck ["Heart","Spade"] [1..n]
-- Note that this defines infinitely many different decks
-- How should I define a card in sillyDeck n? One option is
data Card = Card {suit :: Suit, value :: Value } deriving (Show)
-- but this doesn't reference the deck I'm using. I could try
data Card2 = Card2 {suit2 :: Suit, value2 :: Value, deck2 :: Deck } deriving (Show)
-- but then
cardInWrongDeck :: Card2
cardInWrongDeck = Card2 "Cheese" 999 (sillyDeck 3)
-- is valid, when I'd hope for something like a type error.
-- Of course, I could write a function to check that each card is in the
-- deck it claims to be, and apply it regularly, but that's a horrible solution.
-- Is there a better way to do this?
希望这也解释了我的标题:我想定义一个类型(CardOfType 牌组),它将一些牌组类型的牌组作为参数。我想你不能这样做,但我不知道。
我想做的事情(基本上,有一组对象,每个对象都是一组对象)似乎是一件基本的事情——我敢打赌人们以前也遇到过类似的问题,我希望有一些很好的结构方式解决这个我不知道的问题。
编辑 2:基于 Philip JF 将我指向 GADT(=广义代数数据类型)并进行了一些阅读,我意识到我正在寻找的东西被称为“依赖类型”。所以我原来的标题“带参数的类型”听起来并不那么荒谬。似乎这些在 Haskell 中不存在。我找到了谈论模拟它们的论文,并阅读了显然支持类型函数的 Ωmega。我仍然不知道是否存在一种具有将值作为参数的类型的语言。