David Berry
David Berry

Reputation: 41226

SequenceType of functions

I have a swift implementation of the haskell <*> operator that seems to work as long as the arguments are arrays:

public func <*> <T, U>(left:[(T)->U], right:[T]) -> [U] {
    return flatten(map(left) { (function) -> [U] in
        return map(right) { return function($0) }
    })
}

I'm trying to make it more general by rewriting it to use sequences instead of arrays, but I'm having difficulty with the syntax to require that a sequence be a sequence of functions. This works to generalize the right argument, but not the left:

public func <*> <T, U, Tseq:SequenceType where Tseq.Generator.Element == T>(left:[(T)->U], right:Tseq) -> [U] {
    return flatten(map(left) { (function) -> [U] in
        return map(right) { return function($0) }
    })
}

Now I'm trying to generalize the left part, but running into syntax errors. It seems like it ought to be:

public func <*> <
    T,
    U,
    Tseq:SequenceType where Tseq.Generator.Element == T,
    Fseq:SequenceType where Fseq.Generator.Element == (T) -> U
    >(left:[(T)->U], right:Tseq) -> [U] {
    return flatten(map(left) { (function) -> [U] in
        return map(right) { return function($0) }
    })
}

But that gives me an error on the Fseq... line:

Expected '>' to complete generic parameter list

What is the proper syntax (or is there no proper syntax) to require that Fseq.Generator.Element be a function taking a T and returning a U?

Upvotes: 0

Views: 84

Answers (1)

Airspeed Velocity
Airspeed Velocity

Reputation: 40965

Couple of problems (one fixable, one more fatal):

You have the syntax for the generic template a bit off. There’s only one where clause for all the placeholders, rather than an optional one per placeholder. So it would be more like:

public func <*> <
    T, U, Tseq: SequenceType, Fseq: SequenceType
    where Fseq.enerator.Element == T -> U,
          Tseq.Generator.Element == T>
    (left:[(T)->U], right:Tseq) -> [U] {
        return flatten(map(left) { (function) -> [U] in
            return map(right) { return function($0) }
            })
}

However, that still won’t work because you can’t have expressions more complex than single types on the rhs of a == (not even tuples of two placeholders). So where Fseq.Generator.Element == T->U is not going to fly.

You might want to look at how swiftz does this – looks like it requires an additional struct.

Upvotes: 1

Related Questions