[英]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
都需要能够同时处理Int
和Double
geneState
就是这种情况,因为我可以在离散值和连续值上调用geneState
。
Let's represent the part of this code which consumes the Int
and the Double
separately. 让我们分别代表消耗
Int
和Double
代码部分。 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中,函数
fromIntegral
将Int
转换为其他数字类型。 We can thus write 我们可以写
geneStateAsDouble :: Gene -> Double
geneStateAsDouble = geneState fromIntegral id
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.