haskell-jp / questions #39

えび (ebi_chan)
@えび (ebi_chan) has joined the channel
(もくもく会の中でも相談したが、知見として投稿)
ある型を複数のMonadReaderのインスタンスにできないことで、設計上困っています。
シチュエーションとしては、Xはフレームワークが提供している型で、Yはユーザーが拡張した型、という状況です。
何かしらアドバイスいただけると嬉しいです。
newtype X a = X {unX = ReaderT A IO a}
 deriving
 (MonadReader A)

newtype Y a = Y {unY = ReaderT B X a}
 deriving
 (
  --MonadReader A -- 複数のMonadReaderにはできない
  --MonadReader B
 )

class MonadReader A => C1 where ...
class MonadReader B => C2 where ...
-- YをMonadReader A,Bどちらを要求するコンテキスト下でも使いたい。
@igrep さんから`capability`を使って解決できるのではと教えていただきました。 https://www.tweag.io/posts/2018-10-04-capability.html
ぜんぜん解決策じゃないけど、似たような問題に対して fumi さんの extesnible の extensible effects ならフィールドで切り替えれたような
違ったかも
実際 https://www.tweag.io/posts/2018-10-04-capability.html でも最後の方で、free monadやextensible effectsはcapabilityの特殊なバージョンだ、と触れてますね。
Another solution to many of the same problems has been known for a while: free monads and extensible effects. As it happens, capability and free monads can be formally compared. In this paper, Mauro Jaskelioff and Russell O'Connor, prove that free monads are a special case of capabilities (it's not phrased in these terms, of course, but that's what the paper amounts to).
状況の限られた方法になりますが、 MonadReader a => 制約の掛かった関数に渡したい、という用途であれば (->) a がMonadReaderになる事が利用できるかもしれません。適当にラムダ式でくるめば型が合うかも
許容解かどうか分かりませんが,

newtype YA a = YA (Y a) deriving (MonadReader A)
newtype YB a = YB (Y a) deriving (MonadReader B)

askA = coerce (ask @A @YA)
askB = coerce (ask @B @YB)


みたいなのでもいけると思いますね.この解決策がまさに capability なので,そっちを使える状況ならそっちを使う方がいいと思いますが
素朴な質問なのですが、Haskellって難易度的には高い方なのでしょうか?できない自分が心配です。
ここのサイトで, Haskell は総じて下から数えて数番目にいるので,難しい方とは思いますね.
https://www.quora.com/What-is-a-list-of-programming-languages-ordered-from-easiest-to-hardest-to-learn

個人的にも,難しい方だと思います.ただ,他のプログラミング言語も同程度には覚えることが多いので,そこまで大きな差ではないとは思います.ただ,多くの場合参考文献がプログラミング初心者を想定していないので,その点ではCやJavaなどに(学習環境的に)劣ると思いますね.
ありがとうございます:blush:そんなに難しかったんですね:sweat_smile:自分全く知らなかった笑笑
難しいけど、習得すれば必ず役に立つので頑張って!
@rusconn has joined the channel
インスタンスの意味をネットで調べたのですが、オブジェクト指向時の意味しか記載されてないのですが、haskell上ではどのような意味なのでしょうか?
質問の直接的な答えではないんですけど、そういう時は "インスタンス haskell" で調べる方法が便利でいいですよー
それに関連して、「型クラス」も検索ワードに加えると良いかもしれないですね。
ありがとうございます:blush:自分「インスタンス 静的型」で調べてました笑笑
もし手元に「すごいhaskell楽しく学ぼう」があるのであれば、索引から調べてみてもいい答えが見つかると思いますよ。
それでやってみたところ「振る舞い」と出てきたのですが、haskellでいう振る舞いはどのように動くかという意味でしょうか?
例えば (==) :: (Eq a) => a -> a-> a ->Bool これ全体でインスタンスということでしょうか?
どんな文章のどこでその「振る舞い」という単語が出てきたのでしょうか?
Haskellであれほかの言語であれお察しのとおりプログラミングの文脈で「振る舞い」といえば単に「どのように動くか」ぐらいの意味しかないですが...。 :thinking_face:
ありがとうございます。プログラミングとふつーの日常の意味と違う単語とかあるのでもしかしたら違うのかも、、、って言う感じで聞きました!笑笑
私もぐぐってみたら http://capm-network.com/?tag=Haskell-%E5%9E%8B%E3%82%AF%E3%83%A9%E3%82%B9 というのがヒットしたのですがこれをご覧になったのでしょうか?
ここには「型クラス」が「型のふるまい」だとは書かれていますが「インスタンス」は「型クラスの制約を満たすように定義した型」と書かれていますね。
まず、単に「インスタンス」というと普通は「何かの実例」という意味だと思います。オブジェクト指向言語ではだいたい「int とか String とかの型にたいして、 1, 2, 3 とか "foo" "bar" とかが実例」ということになるわけで、つまり値がインスタンスなのですが
Haskell だと十中八九「型クラスのインスタンス」の話をしているので、レイヤが一個違います。「型クラスとしての Eq, Num に対して、 Int 型や Float 型といったものが実例」です。
ちょっと突っ込むんですが、「すごい Haskell 楽しく学ぼう!」という本を見たんだと思います
:thinking_face: どうなんでしょうね。「それでやってみたところ「振る舞い」と出てきたのですが」の「それ」がどちらともとれたので私も訪ねたのですが。。。
すごいH本を取ってきました。P.27 2.4型クラス初級講座 の冒頭に、「 型クラス は、何らかの振る舞いを定義するインターフェイスです。ある型クラスの インスタンス である型は、その型クラスが記述する振る舞いを実装します。」と書かれていました
つまり、インスタンスは振る舞いなのではなくて、振る舞いを「実装」したもの、つまり振る舞いの「実例」ですね。
あっ、先に書かれてしまいましたがそうです
まあ、「振る舞い」という言葉にまどわされず、ありのまま「型クラス」と「インスタンス」をいろいろ触ってみて体得したほうがいいと思います…。
Haskell が難しい言語というのは、「欧米人にとって日本語が難しい」みたいな感じなんじゃないかなあと思っています。他の多くのプログラミング言語はお互いに似ているところが多いので一個覚えれば次が楽な傾向があると思うのですが、 Haskell はそれらとはだいぶ違う発想が必要になるので…。
でも、本当に一個目のプログラミング言語として覚える際に特別難しいかというと、そうでもないような気がしています。
ただ、最近の GHC 拡張の世界は難しいです^^;私ののーみそは Haskell98 Language Report に毛が生えた程度の水準で止まっています^^;
さらっとしか書かれてないので読み落としがちなのかもしれないけど、型クラスのインスタンスは「型」である、というところが最重要ポイントですよね
オブジェクト指向ではクラス(=型)のインスタンスが値、
Haskellの型クラスは「型クラス」のインスタンスが型、
なので一個ずれている、という。
型クラスの実例が型、型の実例が値、というわけなので、この点をもって、「Haskell の型クラスは、あえていうならオブジェクト指向のインタフェースみたいなものだ」という説明をときどき見る気がしますね。
ああー!! その通り! オブジェクト指向のインスタンスは複数あることもあるんですが、ある文脈において型クラスのインスタンスは一つの型に対して一つしかないんですよね
内部レベルでは型クラスが型だったりインスタンスは値だったりするので、ちょっと混乱してしまったんですが、クラスがそれぞれの値に対してインスタンスを作るのに対して、型クラスがそれぞれの型に対してインスタンスを作るという意味では、そう見れますね
http://capm-network.com/?tag=Haskell-%E5%9E%8B%E3%82%AF%E3%83%A9%E3%82%B9 言い方は悪いですが、ここに書かれている内容はまったくのデタラメであることを付け加えておきます。ほぼすべての記述が間違いなので忘れましょう
@tech_machii has joined the channel
否定するならもうちょっと丁寧にやりませんか。。。
確かに「Interfaceや抽象クラスに相当します」とか「クラスの実装(Implement)に相当します 」とか「show関数やprint関数は、Showのインスタンスです」といった表現はいかがなものかと思いますが、(言葉遣いの厳密さに目をつむって)ざっくりとした理解するには悪くないんじゃないかと思いますが...。
特に「型クラスとは、型の振る舞いを定義するものです。 」とか「インスタンスとは、型クラスの制約を満たすように定義した型のことです。 」なんてすごいH本の記述と特に矛盾しない(参考にした?)ですし、「ほぼすべての記述が間違い」なんて言ってしまっては混乱を招くのでは...
私もいくぶんそう思うのですが、「型クラスとは型の振る舞いを 定義 しているというべきなのだろうか?」とか「インスタンスとは型クラスの 制約 を満たすように…」と書いていいものだろうか?というあたりも気になります。まあその部分だけ見ると 間違いとは 間違いでないとは 言えなくもないのですが、定義という用語や制約という用語をこの説明文中で安易に日常用語の意味で使うのはどうなのかなあ、と…
私が気になったのは、上に加えて「受け取りデータに対する実装」「等価性検査の型」「Showのインスタンスは、文字列表現を返します。」「型クラスの文脈での振る舞い」や、下の「条件式」などですね。全ての節に誤りが含まれているといえるように思えます。

class 型クラス 型 where
 条件式

instance 型クラス 型 where
 条件式
↑日本語おかしかったので修正しました^^;
Haskell の文書をみてたら、何か所かで wurble という関数名とかファイル名が例に出てきたのですが( https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/glasgow_exts.html#visible-type-application とか https://downloads.haskell.org/~ghc/master/users-guide/separate_compilation.html#redirecting-the-compilation-output-s とか)、これ foo, bar, baz と同列の「意味のない文字列を名称に使ってるだけ」と思っていいのですかねえ… 意味を調べても https://en.oxforddictionaries.com/search?filter=dictionary&query=wurble こんな感じですし…
https://stooryduster.co.uk/scottish-words-glossary/words-w.htm をみると crawl forward like a commando sneaking up through the undergrowth (這いよる、っていう感じ?)の意味が書いてるんで、 Glasgow あたりでの方言なんでしょうかねえ
画像検索してみたら出てきた https://www.pinterest.jp/pin/558094578795127725/
まぁまぁかわいいですな。 :bear:
「イギリス圏では加えて「wibble」「wobble」「wubble」「flob」等も用いられる」