質問

この質問は炎上を目的としたものではありません。明らかなように、私は見てきました スカラズ 最近。私は理解しようとしています なぜ ライブラリが提供する機能の一部が必要です。ここに何かがあります:

import scalaz._
import Scalaz._
type NEL[A] = NonEmptyList[A]
val NEL = NonEmptyList

何が起こっているかを確認するために、関数に println ステートメントをいくつか入れました (余談:もしそのような副作用を避けようとしていたらどうしたでしょうか?)。私の機能は次のとおりです。

val f: NEL[Int] => String    = (l: NEL[Int]) => {println("f: " + l); l.toString |+| "X" }
val g: NEL[String] => BigInt = (l: NEL[String]) => {println("g: " + l);  BigInt(l.map(_.length).sum) }

次に、それらを経由して結合します コックライスリ そして、 NEL[Int]

val k = cokleisli(f) =>= cokleisli(g)
println("RES: "  + k( NEL(1, 2, 3) ))

これは何を印刷しますか?

f: NonEmptyList(1, 2, 3)
f: NonEmptyList(2, 3)
f: NonEmptyList(3)
g: NonEmptyList(NonEmptyList(1, 2, 3)X, NonEmptyList(2, 3)X, NonEmptyList(3)X)
RES: 57

RES 値は、最終的な NEL 内の (String) 要素の文字数です。私には次の 2 つのことが思い浮かびます。

  1. 関連するメソッド シグネチャから、NEL がこのように削減されることをどのようにして知ることができたのでしょうか?(結果は期待していませんでした まったく)
  2. これにはどういう意味があるのでしょうか?かなりシンプルでわかりやすいユースケースを抽出できるでしょうか?

この質問は、次のような素敵な人に対する、ベールの薄い嘆願です。 レトロニム この強力なライブラリが実際にどのように機能するかを説明します。

役に立ちましたか?

解決

は結果を理解するには、Comonad[NonEmptyList]インスタンスを理解する必要があります。 Comonad[W]基本的に(Scalazの実際のインターフェースは少し異なりますが、これは説明に役立ちます)3つの機能を提供しています:

map:    (A => B) => W[A] => W[B]
copure: W[A] => A
cojoin: W[A] => W[W[A]]

そこで、ComonadがAとのそれぞれ、「ヘッド」要素(W)、我々は要素ごとに1つの容器(copure)を取得するように容器の内部構造を露出させるように区別しているいくつかのコンテナcojoinためのインタフェースを提供先頭の要素を与えられます。

これはNonEmptyListために実装されている方法は、そのcopureがリストの先頭を返し、cojoinは尾のヘッドと、このリストのすべての尾で、このリストで、リストのリストを返します。

例(私はNonEmptyListNelを短縮しています):

Nel(1,2,3).copure = 1
Nel(1,2,3).cojoin = Nel(Nel(1,2,3),Nel(2,3),Nel(3))

=>=関数はcoKleisli組成物です。どのようにそれf: W[A] => B以外のそれらについて何も知らない、2つの関数g: W[B] => CWを構成するだろうComonadのですか? fの入力タイプとgの出力タイプは互換性がありません。ただし、map(f)を取得し、W[W[A]] => W[B]とそれを構成するgことができます。さて、W[A]与え、あなたはその関数にフィードにcojoinを得るためにそれをW[W[A]]することができます。だから、唯一の合理的な組成物は、以下のことを行い、機能kあります:

k(x) = g(x.cojoin.map(f))

だからあなたの空ではないリストについてます:

g(Nel(1,2,3).cojoin.map(f))
= g(Nel(Nel(1,2,3),Nel(2,3),Nel(3)).map(f))
= g(Nel("Nel(1,2,3)X","Nel(2,3)X","Nel(3)X"))
= BigInt(Nel("Nel(1,2,3)X","Nel(2,3)X","Nel(3)X").map(_.length).sum)
= BigInt(Nel(11,9,7).sum)
= 27
scroll top