I have a type like so,
data AgentSpec a = AgentSpec
{ agent :: a
, events :: [ByteString]
} deriving (Show)
and other types like so,
data Java = Java
data Php = Php
I am trying to create a function of type,
allEvents :: [AgentSpec a] -> [ByteString]
allEvents aspec = concatMap events aspec
But I am unable to create values of type [AgentSpec a]
If I do,
allEvents [AgentSpec Java ["event1, "event2"], AgentSpec Php ["event3, "event4"]]
it does not typecheck and understandably so. It doesn't type check because, AgentSpec Java
is not AgentSpec a
So I understand why it does not work. But I do not know how to overcome this limitation without writing a lot of duplicate code.
One alternatve is to manually construct a list of type,
allEvents :: [ByteString]
allEvents = ["event1", "event2", "event3", "event4"].
But I feel like I'm simply rewriting things I've already modelled in my types. Is there any way to make use of my existing types to get what I want? Which is just a concatenated list of bytestrings of all the AgentSpecs
This code:
allEvents [AgentSpec Java ["event1, "event2"], AgentSpec Php ["event3, "event4"]]
doesn't compile because AgentSpec Java ["event1, "event2"]
and AgentSpec Php ["event3", "event4"]
are of different types, and lists in Haskell can only contain one type. An AgentSpec a [ByteString]
can be created for any type a
, but once created it can't be mixed with values of a different type.
I don't know what exactly you're modeling, but typically I'd recommend something like this:
data Language = Java | Php
data AgentSpec = AgentSpec
{ agent :: Language
, events :: [ByteString]
} deriving (Show)
allEvents = [AgentSpec Java ["event1", "event2"], AgentSpec Php ["event3", "event4"]]
Based on your comment about writing a library, though, it doesn't sound like this would work. Can you elaborate on what you're trying to achieve?
There are some techniques to implement heterogenous lists in Haskell . One thing you can do is:
{-# LANGUAGE GADTs #-}
data SomeAgentSpec where
SAS :: AgentSpec a -> SomeAgentSpec
allEvents :: [SomeAgentSpec] -> [ByteString]
allEvents aspec = concatMap ev aspec
where ev (SAS a) = events a
then,
\> let a = AgentSpec Java ["1.", "java"]
\> let b = AgentSpec Php ["2.", "php" ]
\> allEvents [SAS a, SAS b]
["1.","java","2.","php"]
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.