访问自定义Haskell数据类型的函数

时间:2014-06-15 17:03:15

标签: haskell types

我搜索并搜索了以下内容,尤其是堆栈溢出和Google。如果它已经被覆盖或者如此微不足道,以至于在任何地方都没有被提及,我会道歉。

我为有时离散且有时连续的对象定义了自定义数据类型,如下所示:

data Gene =  Discrete String Int | Continuous String Double 
                 deriving (Eq, Show, Read, Ord)

这里,String表示Gene的名称(例如vWF或某些),数值参数是其状态,离散或连续,如下所示:

bober = Discrete "vWF" 2
slick = Continuous "gurg" 0.45432

我可以使用记录语法来访问Gene的属性,但是有两个不同的名称和状态函数。我想要的是一个访问身份的功能,一个访问状态的功能。对于标识,这很简单,因为这是两个值构造函数的字符串:

geneName :: Gene -> String
geneName (Discrete dName _) = dName
geneName (Continuous cName _) = cName

当我尝试创建一个返回Gene状态的函数时,我遇到了麻烦。我认为模式匹配会起作用:

geneState :: Num a => Gene -> a
geneState (Discrete _ dState) = dState
geneState (Continuous _ cState) = cState

这无法在GHCi中加载,给出:

  

DynamicalModularity.hs:34:35:      无法匹配类型Int' with Double'      预期类型:a        实际类型:双倍      在表达式中:cState      在'geneState'的等式中:          geneState(Continuous _ cState)= cState   失败,模块加载:无。

我尝试使用case语法:

geneState :: Num a => Gene -> a
geneState gene = case gene of (Discrete _ dState) -> dState
                              (Continuous _ cState) -> cState

同样这不会加载:

  

DynamicalModularity.hs:30:56:      无法匹配类型Int' with Double'      预期类型:a        实际类型:双倍      在表达式中:cState      在备选案例中:(Continuous _ cState) - > cState      在表达式中:        案例基因{          (离散_ dState) - > dState          (Continuous _ cState) - > cState}   失败,模块加载:无。

我的问题是:我想做什么和/或好Haskell?我错过了一些明显的东西吗我一直在寻找解决方案。任何帮助将不胜感激。

1 个答案:

答案 0 :(得分:4)

任何会消耗调用geneState结果的代码都需要能够同时处理IntDouble - 显然情况就是这样,因为我可以调用{{1}关于离散值和连续值。

我们代表此代码中分别使用geneStateInt的部分。这两个部分都必须是简单的函数,所以我们可以将它们写成

Double

现在我有这两个部分返回相同的结果,因为消费代码必须始终返回相同类型的事物,无论它是接收离散的还是连续的intConsumer :: Int -> result doubleConsumer :: Double -> result

现在,我们可以使用此信息和模式匹配来编写Gene

geneState

我们可以简化此功能的一种方法是假设我们所有的消费者都单独在geneState :: (Int -> result) -> (Double -> result) -> Gene -> result geneState intConsumer doubleConsumer (Discrete _ st) = intConsumer st geneState intConsumer doubleConsumer (Continuous _ st) = doubleConsumer st 上运行 - 即使输入Double是离散的。这在数学上是合理的,因为Gene包含所有Double egers(如果你愿意,可以使它更正式)。

在Haskell中,函数IntfromIntegral转换为其他数字类型。我们可以这样写

Int