Curried Function w/ Type Parameter

How can I define the following funtion

/* Curry `all()` using `predicate` */
public func allUsing <S: SequenceType> (@noescape predicate: (S.Generator.Element) -> Bool) (_ source: S) -> Bool {
  return source.all (predicate) // Assume `all()` on SequenceType exists
}


Such that a use like this is possible:

var allEven = allUsing ({ (x:Int) -> Bool in return 0 == x % 2 })
// cannot convert value of type 'Int -> Bool' to expected argument type '(_) -> Bool'

allEven([0, 1, 2]) // -> false
allEven([2, 4, 6]) // -> true


Seems the result of `allUsing()` from above ought to be typed as if:

func allEven (S:SequenceType where Int == S.Generator.Element) (_ source: S) -> Bool

but it is not.

Closures can't be generic yet. You'll have to explicitly type it for now.

let allEven: [Int] -> Bool = allUsing {x in x % 2 == 0}


Knowing this, you may come to something similar to the way I do it:

extension SequenceType {
  func first(@noescape predicate: Generator.Element -> Bool) -> Generator.Element? {
  return self.lazy.filter(predicate).first
  }
}

/ The mathematical symbol meaning "for all".
/- Returns: whether all elements of the sequence satisfy `predicate`
func ∀<Sequence: SequenceType>(
   sequence: Sequence,
   @noescape predicate: Sequence.Generator.Element -> Bool
) -> Bool {
   return sequence.first{!predicate($0)} == nil
}

extension IntegerLiteralConvertible where Self: IntegerArithmeticType {
   func divisible(by divisor: Self) -> Bool {return self % divisor == 0}
}

func allEven<Sequence: SequenceType
   where Sequence.Generator.Element: protocol<IntegerLiteralConvertible, IntegerArithmeticType>
>(sequence: Sequence) -> Bool {
   return sequence ∀ {$0.divisible(by: 2)}
}

Your curried function is nealy equivalent to this:

extension SequenceType {
    func all(predicate: Generator.Element -> Bool) -> Bool {
        return !self.contains{!predicate($0)}
    }
}

public func allUsing<S: SequenceType>(predicate: (S.Generator.Element) -> Bool) -> (S->Bool) {
    return {(source: S)->Bool in source.all(predicate)}
}

The result type of `allUsing` with its first argument given is S->Bool. But Swift cannot determine the result type, with just `predicate` is given.


So, if you can specify the result type, you can use it.

var allEven = allUsing ({ (x:Int) -> Bool in return 0 == x % 2 }) as Array<Int>->Bool
allEven([0,1,2]) //->false
allEven([2,4,6]) //->true

You may want to make your `allEven` generic, but as already noted, Swift does not support generic closures.

Accepted Answer

Before you invest too much time into currying, take note of this:

https://github.com/apple/swift-evolution/blob/master/proposals/0002-remove-currying.md

Yes, and if you use the open source toolchain with Xcode, you’ll get a warning and a FixIt for curried functions.

Yes, saw that. Your reply beat my 'needed to be moderated' reply. The proposal is already implemented in the Swift 2.2 release and thus - Curry syntax is gone.


Note: other Swift 3.0 proposals, accepted in 2.2, of "axe 'var' in function parameter lists (and elsewhere)" is a pain, in my view...

Curried Function w/ Type Parameter
 
 
Q