0

問題を示す私のコードの簡略版:

protocol Transformer {
    typealias Input
    typealias Output

    func transform(s: Input) -> Output
}

protocol InputType {}
protocol OutputType {}

extension Int: OutputType {}
extension String: InputType {}

struct StringToInt: Transformer {
    typealias Input = String
    typealias Output = Int

    func transform(s: Input) -> Output {
        return s.characters.count
    }
}

typealias Transform = InputType -> OutputType

func convert<T: Transformer where T.Input == InputType, T.Output == OutputType>
    (transformer: T) -> Transform {
    return transformer.transform
}

convert(StringToInt()) // error: Cannot invoke 'convert' with an argument list of type '(StringToInt)'

StringToIntコンパイラがそれに到達して検証できずInput、実際におよびそれぞれOutputに準拠することができないため、エラーが発生すると推測しています。InputTypeOutputType

私にとって、これを解決する最善の方法は、関連する型をプロトコルで直接制約することです。それはより表現力があり、コンパイラーはより多くの情報を持っています。しかし、ただやるだけではうまくいきtypealias Input: InputTypeません。

関連付けられた型を制約する方法はありますか?

4

2 に答える 2

0

エイリアスの使用を取り除きTransform、入力と出力の型にジェネリックを追加し、それらを にマップすると、作成した他のトランスフォーマー用Transformerの作業コードが得られます。StringToInt

func convert<T: Transformer, I, O where T.Input == I, T.Output == O>
    (transformer: T) ->  I -> O {
        return transformer.transform
}

convert(StringToInt())

ところで、 の型エイリアスを指定する必要はありませんStringToInt。実際の型を指定すると、コンパイラは関数定義からそれらを推測できます。

struct StringToInt: Transformer {

    func transform(s: String) -> Int {
        return s.characters.count
    }
}
于 2016-01-10T14:07:37.713 に答える