jcnm
jcnm

Reputation: 83

Contextual type inference for Type in Swift 2.2+

I want to use first order citizen Type in Swift to decide which function to call.

func sf(v: [Float]) -> Float{
}

func  df(v: [Double]) -> Double {
}

func f<T: RealType>(seq ls: [T]) -> T {
  if T.self == Float.self {
    return sf(ls) // 1. where sf: Float -> Void
  } else if T.self == Double.self {
    return df(ls) // 2. where df : Double -> Void
  }
}

The type inference system couldn't notice that under one branch T == Float and Double in the other ?

Is here a missing feature, complex feature or bug ?

Edit:

typealias RealType = protocol<FloatingPointType, Hashable, Equatable, Comparable, FloatLiteralConvertible, SignedNumberType> 

for my prototype but will become a protocol

Upvotes: 1

Views: 95

Answers (1)

Cristik
Cristik

Reputation: 32826

You are trying to combine static resolution given by generic with runtime decisions, and this is not possible.

You can simply overload f for both Float and Double to obtain what you need:

func f(seq ls: [Float]) -> Float {
    return sf(ls) // 1. where sf: Float -> Void
}

func f(seq ls: [Double]) -> Double {
    return df(ls) // 2. where df : Double -> Void
}

However, if you want RealType to be a generic placeholder that you can use over other types than Float or, Double, then you can do something like this:

protocol RealType {
    static func processArray(v: [Self]) -> Self
}

extension Float: RealType {
    static func processArray(v: [Float]) -> Float {
        return sf(v)
    }
}

extension Double: RealType {
    static func processArray(v: [Double]) -> Double {
        return df(v)
    }
}

func sf(v: [Float]) -> Float{
    return 0
}

func  df(v: [Double]) -> Double {
    return 0
}

func f<T: RealType>(seq ls: [T]) -> T {
    return T.processArray(ls)
}

This will give you both type safety, which is one of Swift's main advantages, and scalability as whenever you need to add support for f over another type, you need to only declare that type as conforming to RealType, and implement the processArray method.

Upvotes: 1

Related Questions