"SubTypes" 带有自己的显示并可用于其他模块



我很确定我的问题源于我是Haskell的新手,并且不完全理解类型系统。

我将使用Haskell的wiki中关于类型主题的示例

以下类型定义为

data Suit = Club | Diamond | Heart | Spade

现在第一个问题是,我想为每个"子类型"(Club、Diamond、Heart、Spade)实现Show,但这似乎不起作用,因为它是DataKinds。所以我把它分成了自己的类型。(属性没有多大意义,但我添加它们是为了更接近真实代码)

data ClubType = ClubType {
clubName :: String,
icon :: String
} 
instance Show ClubType where
show (ClubType cn i) = "name: " ++ cn ++ ", icon: " ++ i

在套装型中使用它们

data Suit = Club ClubType 
| Diamond DiamondType 
| Heart HeartType 
| Spade SpadeType

现在我想在不同的module中使用套装和"子类型"(球杆、钻石、心形、黑桃)。我只导出了Suit (..)

用法

import Module1 (Suit(..))
getSuit :: String -> Suit
getSuit "Club" = getClub
getSuit "Heart" = getHeart
...
getClub :: () -> Club

再次,ClubHeartDiamondSpade不能使用,因为它们是DataKinds。如何使用"子类型"?我需要导出所有类型吗?如果我这样做了,它是否符合getSuit的返回类型?

(很抱歉,如果这个例子没有太多意义,但我希望你能按照我想要的结果)

感谢

是的,听起来你并没有真正理解类型系统。我会尽力澄清我认为你哪里错了。在您的示例中

data Suit = Club | Diamond | Heart | Spade

只有一种类型,那就是SuitClubDiamond等根本不是类型,如果你把它们称为"子类型",你会混淆自己。它们的正确名称是构造函数,它们本质上是Suit类型的值

Club :: Suit
Diamond :: Suit
...

因此,您不能真正为"每一个"实现Show实例,只能通过构造函数上的模式匹配为整个类型Suit实现Show实例:

instance Show Suit where
show Club = "Clubs"
show Diamond = "Diamonds"
show Heart = "Heart"
show Spade = "Spade"

这在类型Suit -> String上定义了一个单独的函数show,同样没有任何"子类型"。我想知道这是否就是你想要的。

既然您提到了数据种类,那么在类型级别使用构造函数仍然不会使它们成为类型——它们仍然是Suit类型的值。在类型级别使用它们的一个例子是通过以下内容索引GADT:

data Card :: Suit -> * where
QueenOfSpades :: Card Spade
OtherCard :: Int -> Card s   -- we'd want to encode the suit s at the data
-- level too using a singleton, out of scope
-- for this post

但这是相当先进的东西,可能不是你想要的。

我希望这能稍微澄清一下。

最新更新