【问题标题】:Contextual type inference for Type in Swift 2.2+Swift 2.2+ 中 Type 的上下文类型推断
【发布时间】:2016-09-24 20:37:23
【问题描述】:

我想在 Swift 中使用一阶公民类型来决定调用哪个函数。

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
  }
}

类型推断系统没有注意到在一个分支下 T == Float 和 Double 在另一个分支下?

这里是否缺少功能、复杂功能或错误?

编辑

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

对于我的原型,但将成为协议

【问题讨论】:

  • 您的代码中如何定义RealType
  • RealType 目前是一个类型别名。我编辑了我的问题以添加它。

标签: swift generics types


【解决方案1】:

您正在尝试将泛型给出的静态分辨率与运行时决策结合起来,这是不可能的。

您可以简单地为FloatDouble 重载f 以获得您需要的内容:

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
}

但是,如果您希望 RealType 成为通用占位符,您可以将其用于除 FloatDouble 之外的其他类型,那么您可以执行以下操作:

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)
}

这将为您提供类型安全性(这是 Swift 的主要优势之一)和可伸缩性,因为每当您需要在另一种类型上添加对 f 的支持时,您只需将该类型声明为符合 RealType,并实现processArray 方法。

【讨论】:

  • 谢谢@Cristik。我正在寻找一个简洁的解决方案,使用 Type 来决定在运行时执行哪个分支。我认为静态分析传递(使用抽象解释)可以允许此代码,因为在 if 分支中意味着条件表达式被评估为真。看来这是不可能的了。如果是这样,将验证您的答案。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多