如何在Haskell中获取标记的联合数据类型中的值?

时间:2014-04-13 11:01:04

标签: haskell

在Haskell中,如果我创建这样的数据表:

data MyT = MyT Int deriving (Show)
myValue = MyT 42

我可以获取Int值,将'myValue'传递给函数并进行模式匹配:

getInt :: MyT -> Int                                                  
getInt (MyT n) = n

在我看来,更简单的事情应该是可能的。还有另一种方式吗?

另外,我尝试了一个lambda函数:

(\(MyT n) -> n) myValue

它不起作用,我不明白为什么不。 我收到错误:

The function `\ (MyT n) -> n' is applied to two arguments,
    but its type `MyT -> Int' has only one

修改 当然,下面的sepp2k,对我的lambda函数工作正常。我在做:

(\(MyT n) -> n) myT 42

而不是

(\(MyT n) -> n) (myT 42)

3 个答案:

答案 0 :(得分:3)

如果你想在没有定义辅助函数的情况下在更大的函数中获取MyT的值,你可以在局部变量定义中使用case of或模式匹配。以下是此示例(假设g生成MyTf生成Int):

使用case

myLargerFunction x = f (case g x of MyT n => n)

或使用局部变量:

myLargerFunction x = f myInt
  where MyT myInt = g x

或使用let代替where

myLargerFunction x =
  let MyT myInt = g x in
  f myInt

你的lambda函数应该(实际上)也可以正常工作。您的错误消息表明,在您的真实代码中,您实际上正在执行类似(\(MyT n) -> n) myValue somethingElse的操作(可能是偶然的)。

答案 1 :(得分:3)

您可以使用记录语法

data MyT = MyT {unMyT :: Int} deriving (Show)

为您提供免费投影

unMyT :: MyT -> Int

如果您的数据类型只有一个构造函数(包括newtype s),这很好。对于涉及多个constrctor的数据类型,投影函数往往是不安全的(例如,headtail),并且通常首选模式匹配。如果启用警告,GHC会检查非详尽模式,并可帮助发现错误。

答案 2 :(得分:2)

NewTypes创建一个不同的类型,并且没有额外的间接级别,如代数数据类型。有关更多信息,请参阅Haskell报告:

http://www.haskell.org/onlinereport/decls.html#sect4.2.3

Prelude> newtype Age = Age { unAge :: Int } deriving (Show)
Prelude> let personAge = Age 42
Prelude> personAge
Age {unAge = 42}
Prelude> (unAge personAge) + 1
43

使用lambda函数:

Prelude> (\(Age age) -> age * 2) personAge
84