简体   繁体   English

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

[英]Accessing functions for custom Haskell data types

I have searched and searched for the following, in stack overflow in particular and Google in general. 我搜索并搜索了以下内容,特别是堆栈溢出和Google。 My abject apologies if it is either already covered or so trivial as not to be mentioned anywhere. 如果它已经被覆盖或者如此微不足道,以至于在任何地方都没有被提及,我会道歉。

I have defined a custom data type for objects that are sometimes discrete and sometimes continuous, like so: 我为有时离散且有时连续的对象定义了自定义数据类型,如下所示:

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

Here, the String represents the name of the Gene (eg vWF or some such) and the numerical parameter is its state, either discrete or continuous, like so: 这里,String表示Gene的名称(例如vWF或其他),数值参数是其状态,离散或连续,如下所示:

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

I could use record syntax to access the properties of a Gene, but then there are 2 different functions for name and state. 我可以使用记录语法来访问Gene的属性,但是有两个不同的名称和状态函数。 What I would like is one function to access identity, and one to access state. 我想要的是一个访问身份的功能,一个访问状态的功能。 For identity, this is straightforward, since that is a string for both value constructors: 对于标识,这很简单,因为这是两个值构造函数的字符串:

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

When I try to make a function that return the state of a Gene though, I run into trouble. 当我尝试创建一个返回Gene状态的函数时,我遇到了麻烦。 I thought pattern matching would work: 我认为模式匹配会起作用:

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

This fails to load in GHCi, giving: 这无法加载GHCi,给出:

DynamicalModularity.hs:34:35: Couldn't match type Int' with Double' Expected type: a Actual type: Double In the expression: cState In an equation for `geneState': geneState (Continuous _ cState) = cState Failed, modules loaded: none. DynamicalModularity.hs:34:35:无法匹配类型Int' with Double'预期类型:a实际类型:Double在表达式中:cState在`geneState'的等式中:geneState(Continuous _ cState)= cState Failed,modules已加载:无。

I tried using case syntax: 我尝试使用case语法:

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

Again this doesn't load: 再次这不加载:

DynamicalModularity.hs:30:56: Couldn't match type Int' with Double' Expected type: a Actual type: Double In the expression: cState In a case alternative: (Continuous _ cState) -> cState In the expression: case gene of { (Discrete _ dState) -> dState (Continuous _ cState) -> cState } Failed, modules loaded: none. DynamicalModularity.hs:30:56:无法匹配类型Int' with Double'预期类型:a实际类型:Double在表达式中:cState在备选案例中:(Continuous _ cState) - > cState在表达式中:case gene of {(Discrete _ dState) - > dState(Continuous _ cState) - > cState}失败,模块已加载:无。

My question is: Is what I want to do possible and/or good Haskell? 我的问题是:我想做什么和/或好Haskell? Am I missing something obvious? 我错过了一些明显的东西吗 I have been searching for a solution for some time now. 我一直在寻找解决方案。 Any help would be greatly appreciated. 任何帮助将不胜感激。

Any code which would consume the result of calling geneState would need to be able to handle both Int and Double —clearly this is the case because I can call geneState on both discrete and continuous values. 任何会消耗调用geneState结果的geneState都需要能够同时处理IntDouble geneState就是这种情况,因为我可以在离散值和连续值上调用geneState

Let's represent the part of this code which consumes the Int and the Double separately. 让我们分别代表消耗IntDouble代码部分。 Both of these parts must be simple functions so we can write them as 这两个部分都必须是简单的函数,所以我们可以把它们写成

intConsumer    :: Int    -> result
doubleConsumer :: Double -> result

Now I have both of these parts return the same result because the consuming code must always return the same kind of thing regardless of whether it receives a discrete or a continuous Gene . 现在我有这两个部分返回相同的结果,因为消费代码必须始终返回相同类型的事物,无论它是否接收离散或连续的Gene

Now, we can write geneState using this information and pattern matching 现在,我们可以使用此信息和模式匹配编写geneState

geneState :: (Int -> result) -> (Double -> result) -> Gene -> result
geneState intConsumer doubleConsumer (Discrete   _ st) = intConsumer    st
geneState intConsumer doubleConsumer (Continuous _ st) = doubleConsumer st

One way we might simplify this function is to assume that all of our consumers function on Double s alone—even if the input Gene was discrete. 我们可以简化此功能的一种方法是假设我们所有的消费者都单独使用Double s - 即使输入Gene是离散的。 This is mathematically justifiable because Double contains all of the Int egers (which can be made more formal if you want). 这在数学上是合理的,因为Double包含所有的Int egers(如果你愿意,可以使它更正式)。

In Haskell the function fromIntegral converts Int s to other numeric types. 在Haskell中,函数fromIntegralInt转换为其他数字类型。 We can thus write 我们可以写

geneStateAsDouble :: Gene -> Double
geneStateAsDouble = geneState fromIntegral id

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM