我搜索并搜索了以下内容,尤其是堆栈溢出和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?我错过了一些明显的东西吗我一直在寻找解决方案。任何帮助将不胜感激。
答案 0 :(得分:4)
任何会消耗调用geneState
结果的代码都需要能够同时处理Int
和Double
- 显然情况就是这样,因为我可以调用{{1}关于离散值和连续值。
我们代表此代码中分别使用geneState
和Int
的部分。这两个部分都必须是简单的函数,所以我们可以将它们写成
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中,函数Int
将fromIntegral
转换为其他数字类型。我们可以这样写
Int