创建方便的类型

时间:2011-07-12 16:25:14

标签: haskell

我从Haskell开始。我有一种情况,可以方便地使用以下类型的同义词:

type Adult = Int
type Youth = Int

但是我不能重载AdultYouth上的函数,即使它们是不同类型的同义词,因此必须有两个单独的函数版本,例如。 doSomethingForAdultdoSomethingForYouth,接下来我尝试了

data Person = Adult Int | Youth Int

然后我可以模式匹配并使用单个版本的函数, 但后来我放弃了在函数声明中使用AdultYouth作为类型的选项,这很方便。有中途吗?我看了Either,但是从教程中的描述来看,这似乎是误用的?类似于小型类型层次结构的东西Person位于根,YouthAdult派生而且仍然是Int的同义词,这将是完美的,但我无法弄清楚如何。

5 个答案:

答案 0 :(得分:7)

我不明白这会被误用Either。正如(,)是通用product type一样,Either完全可以接受为通用sum type,即任何形式:

data T = T1 A | T2 B C

...可以被代数地视为A + (B * C),相当于Either A (B, C)

另一方面,如果您想区分AdultYouth,使用相同实际类型的同义词可能会适得其反;它们只是透明的别名。另一种方法是使用newtype s,如下所示:

newtype Adult = Adult Int deriving (Eq, Ord, Show, Read, Num) 
newtype Youth = Youth Int deriving (Eq, Ord, Show, Read, Num) 

调整deriving条款以品味;我在这里添加了Num,因为底层类型是数字,但如果您想要的只是一个唯一标识符,那么添加或乘以它们就没有意义。此时,如果您愿意,可以使用Person的和类型,或者定义类型类以获得正确的重载:

class Person a where 
    -- (etc...)

instance Person Adult where -- ...
instance Person Youth where -- ...

Person中定义的任何函数都会在AdultYouth上有效重载,让您dispatch based on type the way "overloaded" functions in other languages do

答案 1 :(得分:4)

您想要typeclass吗?

data Adult = Adult Int
data Youth = Youth Int

class Person a where
  doSomething :: a -> b

instance Person Adult where
  doSomething (Adult i) = ...

instance Person Youth where
  doSomething (Youth i) = ...

这是Haskell中重载函数的典型方式。类型类Person只有一个函数doSomething :: a -> b。您希望成为Person实例的每种数据类型都可以拥有自己独立的实现。如果您希望底层实现相同,那么只需使用另一个函数doSomethingGlobal :: Int -> b,并让每个实例都等于这个新函数。

答案 2 :(得分:1)

你可以同时拥有:

type Adult = Int
type Youth = Int

data Person = Adult Adult | Youth Youth

数据构造函数与类型在一个单独的命名空间中,因此这里没有冲突。

答案 3 :(得分:0)

我建议只添加类型同义词

type Person = Int

你可以为那些兼顾两种功能的功能提供类型,例如

doSomething :: Person -> ...

(并且您可以在其他类型签名中使用AdultYouth

答案 4 :(得分:0)

我建议Person多态:

data Person a = Person a Int

使用此定义,您可以编写Person级别的一般函数,而不关心a的具体值:

getInt :: Person a -> Int
getInt (Person _ i) = i 

incInt :: Person a -> Person a
incInt (Person p i) = Person p (inc i) 

然后,您可以定义“标签”以证实Person

data Adult = Adult
data Youth = Youth

现在您可以为特定类型的Person

编写函数
rock :: Person Youth -> String
rock (Person Youth k) = "I rock until " ++ show k ++ " in the morning!!!"