克服haskell中多态类型的限制

时间:2016-02-28 23:45:22

标签: haskell

我有类似的类型,

WM_SYSCOMMAND

和其他类似的,

data AgentSpec a = AgentSpec 
                     { agent :: a
                     , events :: [ByteString] 
                     } deriving (Show)

我正在尝试创建一个类型的函数,

data Java = Java
data Php = Php

但我无法创建allEvents :: [AgentSpec a] -> [ByteString] allEvents aspec = concatMap events aspec

类型的值

如果我这样做,

[AgentSpec a]

它并不是一个可以理解的问题。它没有输入格式,因为allEvents [AgentSpec Java ["event1, "event2"], AgentSpec Php ["event3, "event4"]] 不是AgentSpec Java

所以我理解为什么它不起作用。但我不知道如何在不编写大量重复代码的情况下克服这一限制。

一个替代方案是手动构建类型列表

AgentSpec a

但是我觉得我只是在重写我已经在我的类型中建模的东西。有没有办法利用我现有的类型来获得我想要的东西?这只是所有AgentSpecs的字节串的连接列表

2 个答案:

答案 0 :(得分:3)

此代码:

allEvents [AgentSpec Java ["event1, "event2"], AgentSpec Php ["event3, "event4"]]

没有编译,因为AgentSpec Java ["event1, "event2"]AgentSpec Php ["event3", "event4"]的类型不同,而Haskell中的列表只能包含一种类型。可以为任何类型AgentSpec a [ByteString]创建a,但一旦创建,就无法与其他类型的值混合使用。

我不知道你究竟在做什么建模,但我通常会推荐这样的东西:

data Language = Java | Php

data AgentSpec = AgentSpec 
                     { agent :: Language
                     , events :: [ByteString] 
                     } deriving (Show)

allEvents = [AgentSpec Java ["event1", "event2"], AgentSpec Php ["event3", "event4"]]

根据你关于编写图书馆的评论,听起来并不像这样。你能详细说明你想要实现的目标吗?

答案 1 :(得分:2)

implement heterogenous lists in Haskell有一些技巧。你可以做的一件事是:

{-# LANGUAGE GADTs #-}

data SomeAgentSpec where
    SAS :: AgentSpec a -> SomeAgentSpec

allEvents :: [SomeAgentSpec] -> [ByteString]
allEvents aspec = concatMap ev aspec
    where ev (SAS a) = events a

然后,

\> let a = AgentSpec Java ["1.", "java"]
\> let b = AgentSpec Php  ["2.", "php" ]
\> allEvents [SAS a, SAS b]
["1.","java","2.","php"]
相关问题