ここでは以下のコードのためのscasteです。まず、items.cgi
は、次の形式で項目オブジェクトのリストを返しますスカラ座、どちらか[_、配列[いずれかの[_、T]]のいずれかに[_、配列[T]]
$ curl http://example.com/items.cgi
[
...
{ sn: "KXB1333", ownerId: 3, borrowerId: 0 },
{ sn: "KCB1200", ownerId: 1, borrowerId: 2 },
...
]
borrowerId == 0
は、アイテムが何の借り手を持っていないことを意味します。
第二に、users.cgi
は、id
クエリパラメータ
$ curl http://example.com/user.cgi?id=1
{ id: 1, name: "frank" }
で指定されたユーザーを返すAPIが悪いかもしれないが、私はそれに対処する必要があります。今、Scalaで私はまた、HTTPを行うために、以下のいるこの素敵なデータモデル
case class User(id: Int, name: String)
case class Item(sn: String, owner: User, borrower: Option[User])
で作業したい
case class ApiFail(reason: String)
def get[T](url: String): Either[ApiFail, T] = ??? /* omitted for brevity */
get()
機能はURLからJSONを取得するためにいくつかの魔法を使用していますを要求そこからT
を作ります(いくつかのライブラリを使います)。 IOエラーまたはHTTPステータスが不良の場合は、Left
を返します。私は、各項目がどの HTTPをリンクし、ユーザーをフェッチし、Item
Sの新しいリストを返すか、に失敗するのは、項目のリストを取得する必要があり、以下の機能
def getItems: Either[ApiFail, Seq[Item]]
を書きたいと思い
要求の失敗。 (そこに同じIDを持つユーザーのための冗長要求かもしれないが、私はまだおよそメモ化/キャッシュを気にしないでください。)
は、これまでのところ私はこの関数を記述するために管理
def getItems: Either[ApiFail, Seq[Either[ApiFail, Item]]]
場所一部のユーザーの検索に失敗した場合は、結果全体ではなく、対応する項目のみが致命的です。ここでは実装が
def getItems: Either[ApiFail, Seq[Either[ApiFail, Item]]] = {
case class ItemRaw(sn: String, ownerId: Int, borrowerId: Int)
get[List[ItemRaw]]("items.cgi").flatMap(itemRawList => Right(
itemRawList.map(itemRaw => {
for {
owner <- get[User](s"users.cgi?id=${itemRaw.ownerId}")
borrower <-
if (itemRaw.borrowerId > 0)
get[User](s"users.cgi?id=${itemRaw.borrowerId}").map(Some(_))
else
Right(None)
} yield
Item(itemRaw.sn, owner, borrower)
})
))
}
だこれは宿題のための要求のように思えるが、私が別のラッパー事(M-モナド?)から切り替えたいと私は少し困惑だと頻繁に私に起こりますラッパー関数(c-combinators?)のみで行う方法についてです。私はもちろん、命令的な実装に切り替えることができます。私はちょうど興味がある。
は、詳細な説明をありがとうございました。学ぶべきことがたくさんあります。 'traverse'の型パラメータはやや困惑しています。私は3つ必要だとソースから見てきましたが、2つしか指定しません。これは '-Ypartial-unification' scalacフラグ付きの型パラメータなしで動作します。 https://scastie.scala-lang.org/8c1pdg7eTeqzQGRUDLPQOw – woky
catsは、simulacrum(https://github.com/mpilquist/simulacrum)を使用して、タイプクレーンの構文を追加します。トラバースメソッドは実際に 'Traverse.Ops'クラスなどで生成されたもので、' List'からの暗黙の変換を行います。 'F'と' A'型のパラメータは、それを呼び出すオブジェクト( 'itemRawList')から得られ、' G'型と 'B'型のパラメータだけが必要です。 –