[英]Overcoming limitation with polymorphic type in haskell
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]
但是我无法创建[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
它不键入检查,因为, AgentSpec Java
不是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 这只是所有AgentSpec字节串的串联列表
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. 无法编译,因为AgentSpec Java ["event1, "event2"]
和AgentSpec Php ["event3", "event4"]
具有不同的类型,并且Haskell中的列表只能包含一种类型AgentSpec a [ByteString]
可以是为任何类型a
创建a
,但一旦创建就不能与其他类型的值混合。
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 . 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"]
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.