変換関数を実行したくない場合は、いくつかのオプションがあります。高次関数を使用した変換オンオプションのスカラ型クラス
現在のオプションを処理するメソッドは次のようになります。
def writeOptionalXml[T](content: Option[T], mapFn: T => Xml): Xml =
content match {
case Some(c) => mapFn(c)
case None => NodeSeq.Empty
}
そして、それは素晴らしい作品。しかし、私はオプションではありませんが、空の文字列、空のxmlノードやいくつかのケースクラスなど、空のままであるその他の入力もあります。
私は型クラスにリファクタリングするのは良い学習体験と思っていました。多くのコードの論争の後、私はオプションのタイプを処理するために文脈の境界を使う必要があることを発見し、私は自分のタイプクラスの夢を達成するうえでうまくやっていると思った。
ここでは、変換関数(mapFnなどの名前が悪い)を使用しています。 (コンテンツ:Option [T]、mapFn:T => Xml): の場合は、 (入力:A、mapFn:A => Xml)のメソッドシグネチャが必要です。 :Xml
私はタイプシグネチャを変更することに苦労しました。[_]を使用して試してみました。
私は何でもある瞬間、で持っていますが、かなり、このようなコードの合成されたバージョン:
import scala.annotation.implicitNotFound
object writableTypes extends App {
type Xml = String
@implicitNotFound("No member of type class in scope for ${T}")
trait WritableLike[A] {
def toXml[B](input: A, mapFn: ((_$1) forSome {type _$1}) => Xml): Xml
}
object WritableLike {
implicit object WritableLikeString extends WritableLike[String] {
override def toXml[B](input: String, mapFn: ((_$1) forSome {type _$1}) => Xml): Xml =
mapFn(input)
}
implicit def OptionFormat[T: WritableLike]: Object = new WritableLike[Option[T]] {
override def toXml[B](input: Option[T], mapFn: ((_$1) forSome {type _$1}) => Xml): Xml =
mapFn(input.get)
}
def writeXml[X](input: X, mapFn: ((_$1) forSome {type _$1}) => Xml)(implicit ev: WritableLike[X]): Xml =
ev.toXml[X](input, mapFn)
}
println(WritableLike.writeXml(Option(SomeCaseClass(5)), transformToXml))
case class SomeCaseClass(content: Int) { def someMethod = ""}
def transformToXml[T](input: SomeCaseClass): String = input.someMethod
}
残念ながら、これは、このメソッドの呼び出し WritableLike.writeXml(オプション(であるためコンパイルされません。 SomeCaseClass(5))、transformToXml)
関数transformToXmlは、必要なメソッドシグネチャを満たしていません。
私はこれほど多くの順列を試してきましたが、それ以外の方法で解決策を見つけることはできません。
すべてをオプションにすることで簡単に解決できる方法があると確信していますが、私はそれを真に汎用的にするソリューションを見つけることにもっと興味があります。
私はこれを非常にうまく説明しているとは思えません。タイプクラスを書くのは私の最初の試みですが、私はそれは簡単だと思いましたが、解決しようとしている特定の問題がいくつか複雑です。
Scalaタイプのシステムで一般的なプログラミングをより深く理解してくださった方のお話をいただき、大変感謝しています。
おかげ
この回答が役立ちます。ご質問がありましたら、ここでコメントしてください。答えを広げることができるかどうかがわかります。 :) –
こんにちはJaakoはあなたの答えに感謝します。 より幅広いコンテキストでは、いくつかのフォーマッタがあり、それぞれがケースクラス、文字列、日付、その他のnodeseqs(NodeSeqとして)の組み合わせからxml NodeSeqを生成します。空の文字列、nodeseqsまたはNoneのオプション[caseclass]があることがあります。 さまざまなxmlタグを使用してxmlドキュメントの異なる部分を生成するために、複数の場所(フォーマッタあたり)でケースクラスが使用されることがあるため、渡された関数でノードを生成する柔軟性が重要です。 –
ビジネスケースはうまくいきましたが、私はScalaの型クラスパターンの力と限界を探求したかったのです。 これは言語やパターンの制限ですか? それは可能であるように感じます。 –