I'm writing a parsing library - I have a situation where I want to be able to turn any parser that spits out a list of characters int a parser that spits out a string - eg so I can say something like:
let parseWhitespace = Parse.any_of( " ", "\t").many().text()
so I naively wrote:
extension Parser
{
public func text() -> Parser<String> where T : [Character]
{
map( {String($0)} )
}
}
but that got upset with me - saying "type T constrained to non-protocol non type class"
A bit of googling later - and I came up with the craziest hack, which is the following:
public protocol CharacterArray {}
extension Array : CharacterArray where Array.Element == Character
{
}
extension Parser
{
public func text() -> Parser<String> where T : CharacterArray
{
map( { String(($0 as? [Character])!) })
}
}
which works. But is ridiculous - and worst - it has a cast in it. Is there any way of doing this without a cast?
CodePudding user response:
When you want to constrain an associated type to be an exact concrete type, you use ==
instead of :
.
public func text() -> Parser<String> where T == [Character]
// ^^ instead of a colon