haskell-jp / random #25

:sweat_smile: HaskellDayのハッシュタグが被ってしまったか。。。まぁ、Haskellってもともと人の名前だし、しょうがないか。。。
https://twitter.com/USIndianAffairs/status/1041702224534138881
どうやらプログラミング言語の方の名前の由来となったHaskell Curryさんとも関係がない、別のHaskellさんみたい。
https://en.wikipedia.org/wiki/Haskell_Indian_Nations_University
The school was named after Dudley C. Haskell, a member of the U.S. House of Representatives from the 2nd district of Kansas.
ああああああ!知ってる!最初大学ぐるみでHaskellを推進しているのかと勘違いしてました。
「Haskell入門ハンズオン」イベントのハッシュタグが #Haskell なのも他の Haskellさんと被りがち。
自作ライブラリをhaddockでドキュメント作ってみてみたらテンション上がりました
あとちゃんとドキュメント書くと文明的になりますね
@tkskzyk0925 has joined the channel
Haskell初心者なので、見当違いのことを言っているかもしれませんが、質問させてください :bow:

※全てGHCi v8.0.2で処理を行っています

fmapap を用いることで、任意個の引数を持つ関数と任意個のFunctorに対して、以下のような計算が行えるかと思います:

(*) <$> Just 1 <*> Just 2 => Just 2


ここで、TupleもFunctorのインスタンスであることを知り、以下のような計算を考えてみました:

(*) <$> (1, 1) <*> (2, 2) => (1, 2) となることを期待


しかしながら、上記の式はShowのインスタンスとして解決できないという趣旨のエラーにより、期待する結果が得られませんでした。

そこで、ステップごとに型を確かめてみたところ:

:t ((*) <$>)
((*) <$>) :: (Num a, Functor f) => f a -> f (a -> a)

:t ((*) <$> (1,1))
((*) <$> (1,1)) :: (Num t, Num a) => (t, a -> a)

:t ((*) <$> (1,1) <*>)
((*) <$> (1,1) <*>) :: (Num t, Num b, Monoid t) => (t, b) -> (t, b)

:t ((*) <$> (1,1) <*> (2,2))
((*) <$> (1,1) <*> (2,2)) :: (Num t, Num b, Monoid t) => (t, b)


これより、 ap を適用した時点で第一要素にMonoidの型制約が入っており、これがエラーの原因かと考えています。

なぜ ap を適用した時点でMonoidの型制約が入るのでしょうか?これは、TupleがApplicativeのインスタンスとして何か特殊化されているためなのでしょうか?
またもし上記が正しい場合、特殊化を回避すれば期待する計算結果は得られるのでしょうか?

長文となりましたが、ご教授いただければ幸いです :haskell:
tにMonoidが入るのは、そのApplicativeインスタンスの制約にMonoidが入るからですね!
Monoid t => Applicative ((,) t)
https://www.stackage.org/haddock/lts-12.12/base-4.11.1.0/Prelude.html#t:Applicative
ありがとうございます!

こちら、最初は変な挙動に思えていましたが、第一要素を無視するのであればそもそもで文脈としてのFunctor(Maybeの様な)を使えば良いのかなと
第一要素を活かしてApplicativeとしての連鎖を許すなら、第一要素はMonoidとして連結していく方が自然かつ有用ということなんですかね

このあたり、何か数学的・圏論的な背景もあったりしたら別途知ってみたいです :haskell:
端的に言うと、ソース読めやおらぁ?!(大汗) ってことになるわけですが、 (u, f) <*> (v, x) = (u <> v, f x) というApplicativeインスタンスの宣言(一部抜粋)がなされてたので、タプルの左側の型の <> の仕方わかんないんだけど(怒り) と言われてるのだと思います。
(*) <$> (1, 1) <*> (2, 2) => (1, 2) となることを期待

とのことですがこの (1, 2) はどういう計算結果ですか。
2 は 1*2 の結果かなと思うのですが 1 の方は第一要素の最初に出てきた 1?
少し補足なのですが,
第一要素を活かしてApplicativeとしての連鎖を許すなら、第一要素はMonoidとして連結していく方が自然かつ有用ということなんですかね
というのは正しいのですが,
(*) <$> (1, 1) <*> (2, 2) -- => (1, 2)

という動作で実装されていないのはそもそもこういう動作をApplicativeにすることが困難だからです.
理由は単純でApplicativeクラスのpureを実装できないからです.つまり,以下のような式において?の要素を埋められないからです.
pure 2 :: (Int, Int) -- => (?, 2)

デフォルト値として0を入れればいいのではないかという見方もできますが,デフォルト値というのは行いたい演算によって変わってくるので,Int型(や他の全ての型)でデフォルト値を一意に決めることは通常できません.

Monoidのインスタンスであればデフォルト値が決まりますし,apのための演算も提供できるというのがMonoidインスタンスで実装されている主な背景です(これは圏論でのApplicative functorの捉え方とも関連性はあるのですが,あまり安易な解説をしてる文献は知らないですね… 興味があれば, https://bartoszmilewski.com/2017/02/06/applicative-functors/ とかを読んでみるといいかもしれません)

ところで,全ての型に強制的にデフォルト値を足して,演算として最初の要素をただ単に返すMonoidインスタンスを持つデータ型はFirst()という名前で提供されていて,これを使えばおそらく最初に期待した動作は得られます.
(*) <$> (First (Just 1), 1) <*> (First (Just 2), 2) == (First (Just 1), 1 * 2)
@mizunashi-mana pure が実装できないというのはすごく納得です!ありがとうございます :slightly_smiling_face:
http://www.tsurucapital.com/en/ Tsuru Capitalはインターン(3ヶ月)の募集を再開しています。選考は難易度低めのコードサンプル()が主体で、正しい結果を出すのはもちろんですがコードの品質、速度なども評価されます。腕に自信のある方はぜひ
「腕に自信のある方は」は余計だったかもしれない。比較的簡単な問題の割に応募数も正答率も低いので狙い目ですよ
@ababjam61 has joined the channel
Language.Haskell.TH.SyntaxaddDependentFile をStackで使ってたら package.yamlextra-source-files に該当ファイルを書いておかないと検知してくれないという罠にかかりました
GHC のビルドシステムが Hardian になるみたい。
すみません。
リンク先をみてよくわからなかったのですが、これを使う目的・利点はどの辺に書いてありますか?
また、GHC以外には使えない・使いにくい何かがあるのでしょうか。
Haskell Symposium 2016 paperですね。失礼しました。
https://dl.acm.org/authorize?N41275
約20%の確率で来年の年明けにフィリップ・ワドラー氏が来日する可能性があります。実際にはもっと可能性が低いので小ネタ程度に捉えてください。。!
>数学的・圏論的な背景
Applicativeは自己函手の圏でDay convolutionを積とした場合のモノイド対象で、MonoidはSet圏のモノイド対象である事がちょっと関係あったりするかもしれないなあと思いました(小並感)
その説はオーソドックスけど、個人的に、monoidal functor として解釈する方がわかりやすいと思う、Coendなどのことを要らなくなる
GHC向けrbenv的なやつかな?stack使いたくなければこれを使え、と。
https://github.com/haskell/ghcup
@cosmiafu そのあたりを調べるとあたりがつくんだろうなと考えて、 http://www.staff.city.ac.uk/~ross/papers/Applicative.pdf を読んでいるのですが、2-Tuple Applicativeの実装として自然に上述のものが得られる根拠は 4. Monoids are phontom Applicative functors に記述されているのかなと理解しました
( newtype Accy o a = Acc { acc :: o } に対して、 a を無視しない適切な構成を考えると2-Tuple Applicativeの実装になるかなと)
ちなみに、ghc8.6やmasterブランチでも、hadrianでのビルドが可能です。
(マシンによってはビルドが速くなります。)

以下もGHC用の関連リンクです。
https://ghc.haskell.org/trac/ghc/wiki/Building/Hadrian/QuickStart
僕が想定していたのは,monoidal functorから導き出すものですね. <@UDC1LV887> さんが上げているPDFにある通り,Applicativeは(Strong) monoidal functorと一致します.

monoidal functor同士の積はmonoidal functorになります.(m, -) ~ Const m * Identityで,
instance Monoidal Identity where
unit = Identity ()
Identity x * Identity y = Identity (x, y)
と書けますから,後はConst mからmonoidal functorが作れれば自明な(m, -)のmonoidal functorが導出できます.Const m上ではfmapは意味を為さないので,ここから算出されるmonoidal functorはHaskでは唯一で,それが 4. Monoids are phontom Applicative functors に記述されている Accy ですね.

この(m, -)の実装は一般にはWriter Monadと呼ばれています.
<@U57D08Z9U>
Const m * Identity が 2-Tuple Applicativeになるよねというふわっとした理解がより補強されました、ありがとうございます!(唯一であることも気になっていたので、完全にすっきりしました :haskell: )
@jonathan.s has joined the channel
ちょろっとやってみました:HaskellでDhallをExtensibleのレコードとして読み込めるようにする - Qiita - https://qiita.com/A_kirisaki/items/a72cb21be08c6dd7cf92
自分のやつも少し詳しく考えてみました。

関手(a,)から(b,)への自然変換は `forall x. (a, x) -> (b, x)` ですが、これは関数 `a->b` と同型です。
したがってこの自然変換を射とする圏、すなわちHask^Haskの関手圏の部分圏 (*,) と、関数を射とするHask圏は圏同値になります。
a->bを上記の自然変換にマップする関数を以下の通り定義しておきます。

```
iso1 :: (a->b) -> (a, x) -> (b, x)
iso1 f = \(a, x) -> (f a, x)
```
さらに、Data.Functor.Day () で定義されるDayについて、

Day (a,) (b,) x = forall p q. Day (a, p) (b, q) (p -> q -> x)
<-> ((a, b) (forall p q. (p, q, p -> q -> x))
<-> ((a, b), x)


という同型を考えられますが、これは前述の圏同値でHaskの (a, b) に対応する対象になります。つまり、圏同値によって(,)はDay convolution(の同型)に対応します。
Day (a,) (b,) x((a,b), x) にマップする関数を以下のように定義しておきます。

iso2 :: Day (a,) (b,) x -> ((a, b), x)
iso2 (Day (a, p) (b, q) f) = ((a, b), f p q)
以上より圏同値によって、(,)をモノイド積としたHaskのモノイド対象Monoidは、Day convolutionを積とした(*,)のモノイド対象Applicativeと一対一関係になります。

実際、(*,) の `<*>` は `\x y -> iso1 (uncurry (<>)) . iso2 $ day x y` によって作られます。
確かに、Dayという概念を理解するためにEndの概念が必要で(私もあまりちゃんとは理解できてないと思います)、 @cosmiafu さんが仰るように直観性に欠けるとは思います。
Haskell Community Priorities for GHCについてのsurveyだそうです。
https://docs.google.com/forms/d/e/1FAIpQLSdh7sf2MqHoEmjt38r1cxCF-tV76OFCJqU6VabGzlOUKYqo-w/viewform
GHC本体に6カ月間コミットしてくれる人がいたとして、何をして欲しいのか、具体的に書いて欲しいとのこと。
HIWでも似たような議論をしたので、それをさらに広くとる試みのようです。
:point_up: に対応した dhall-haskell の新しいバージョンもリリースされましたね :tada:
https://github.com/dhall-lang/dhall-haskell/releases/tag/1.18.0
ByteStringで失敗した話:[HaskellでのQuickCheckとData\.ByteString\.Char8の罠 \- Qiita]()
似た原因のバグを踏んだことがあります... https://github.com/syucream/hastodon/issues/4 Char8.packはdeprecateした方がいい予感
というかChar8使わず Data.Word8 使うべきなのかもしれませんね
OverloadedStrings 使ってるときも同じ理由で良くハマるんですよね... :disappointed:
cassavaみたいな、テキストファイルを扱うけど入力はByteStringなライブラリーがあって、そいつを使ったテストを書く際に入力を日本語が混ざった文字列リテラルで渡すと... :scream:
私もOverloadedStringsでやられました。今更インスタンスを消すわけにはいかないので、encodeUTF8 . Data.Text.packにしてもよいような…
:open_mouth: https://www.tweag.io/posts/2018-10-04-capability.html やっと読めたんですけど、これすごいっすね。
これで速度に問題がなければ事実上の標準になるのでは。
HList-like indexed transformer?
QuickChekが ByteStringArbitary のインスタンスを作っていてくれればこんなことには……
それは http://hackage.haskell.org/package/quickcheck-instances を使え、ということになるのでは。quickcheckとしては依存関係を絞りたいんでしょう。(もちろん [Word8] から簡単に作れちゃう、というのもありますし)
アッこんなライブラリが!ありがとうございます
@boomehlang has joined the channel