我有类似的类型,
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的字节串的连接列表
答案 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"]