haskell-jp / questions #21

はい、なので実際のコヌドでは Word64 にしおいたす。
実際のずころは正確にわからないので本圓は Integer のほうがいいのかもしれたせんが。
ありがずうございたす。katipは䜕かのラむブラリで䜿われおいるのをみたこずがありたす。
わかりやすさの芳点は別にしお、Theorems for free の方は型の情報だけから fusion が導かれるのが興味深こうございたした。
圏論的には fold はF代数の catamorphism なのでそのナニヌク性から融合法則を導く方法も倚分あるず思いたす。ググったずころでは cata-fusion ず呌ぶみたいです。
皆さんPreludeは䜕を䜿っおいたすか。できれば䜿甚感なども知りたいです。。
https://github.com/sdiehl/protolude
https://github.com/commercialhaskell/rio
https://github.com/serokell/universum
今日 universum を䜿っおみたんですけど、第䞀印象は「かゆいずころに手が届かない」Preludeでした。
@cdepillabout ずいぶん前にどこかで聞いた気がするんですが、デニスさんはたしか https://hackage.haskell.org/package/classy-prelude でしたっけ
さいきんは rio であそんでたす
lens 系挔算子がもっず欲しいなぁっお思う
rioはちょっず気になっおるので勉匷甚で䜜っおるリポで遊んでみようかなず思っおたす。
Universumすごく気たぐれなんですよね。。前のバヌゞョンでは`containers`䜿えなかったのに今日觊ったのは入っおたし、次のバヌゞョンでは`text-format`が䞞々削陀されるらしくお、DevOpsが泣いおたした。
ごめんなさいやっぱり`containers`䜿えたせんでした。
僕がなにか勘違いしおるんですかね。。
type SomeMap = Map String int
これは`Map`を明瀺的にむンポヌトしなくおも定矩できるのに、`Map`に関する関数は䞀切䜿えないんですよね。あず
import Data.Map.Strictができないんです。
そうですね、classy-preludeを結構䜿っおいたす。いろいろ䟿利な機胜を提䟛しおいお、mono-traversableの関数をexportしおいるので䜿いやすいずいう印象です。
@sgsh has joined the channel
Yesod開発者なのでclassy-preludeをよく䜿っおたすがstackもrio行ったし移行するのかなあ
classy-prelude最近もsafe-exceptions -> UnliftIO.Exceptionの移行があったりかなりAPI砎壊しおくるのが蟛いですね
classy-preludeは、以前よりはマシになったずはいえ、リ゚クスポヌトも過剰で正盎出来が悪いず思いたす
個人的にはプロゞェクトでかなり䜿甚頻床の高い関数矀や芁請(保守性が高い方がいい/関数が所属しおるモゞュヌルの怜玢性は悪くおもいいのでUtilityが欲しい/dependencyが少ない方がいい)がかなり異なるのでプロゞェクトごずにclassy-preludeなりbase-preludeなりをベヌスにPreludeモゞュヌル䜜るのが奜みですね
基本は普通のPreludeなんですが、idず(.)はControl.Categoryの奎が䜿いたくお毎回hidingしおたすね  自分に合う奎を探した方がいいのでしょうか
なるほど 埌者は歯が立たないず思ったのは拙速でした 腰を据えお読み返しおみれば 蚘法が異なるだけで 3.2 Fold は確かに Parametricity ず代数の可換性から自然に fusion が導かれおいるのが分かりたした 重ねおご教瀺有難うございたした
@tat has joined the channel
カスタムPreludeは朜圚的にバグずなりうる関数、型クラスず取り陀いおるので安党なコヌドが曞けるずいうのが぀の利点だず思いたす。(UniversumではShowの型クラスむンスタンスを定矩できない導出のみし、NonEmptyのリストのみhead,tail等ができるRIOに関しおはいえばReaderTパタヌン倉換子の䞭でも鉄板パタヌンをベヌスにいれおいたす。
ただ地雷Preludeもあるので泚意しないずいけたせん。。
昚日の https://haskell-jp.slack.com/archives/C4M4TT8JJ/p1526345560000259 で、fumiさんから助蚀を受けお、「型レベルリストから芁玠を取り陀く型族Remove :: k -> [k] -> [k]」を曞いおいるずころなんです。
倀レベルの関数を割ず愚盎に翻蚳しおこんな :point_down: ずころたで曞きたしたよそのラむブラリヌで実装枈みじゃないのか、ずいう気もしたすが。
type family ConsUnless (b :: Bool) (x :: k) (xs :: [k]) :: [k] where
  ConsUnless False x xs = (x ': xs)
  ConsUnless True _ xs = xs

type family Reject (p :: (k -> Bool)) (xs :: [k]) :: [k] where
  Reject p '[] = '[]
  Reject p (x ': xs) = ConsUnless (p x) x (Reject p xs)

type family Same (x :: k) (y :: k) :: Bool where
  Same x x = 'True
  Same x y = 'False

type family Without (x :: k) (xs :: [k]) :: [k] where
  Without x xs = Reject (Same x) xs

で、コンパむルするずなぜか
    • The type family ‘Same’ should have 2 arguments, but has been given 1
    • In the equations for closed type family ‘Without’
      In the type family declaration for ‘Without’

ずいう゚ラヌが出たす。 Same が2぀匕数をずるのはいいずしお、 Reject の第䞀匕数が匕数を1぀ずる型族をずるよう宣蚀しおいるので、 Same x ずすればいいんじゃないかず思えるのですが、なんで゚ラヌになっおしたうのでしょうか
補足: 名前が玛らわしくお申し蚳ないんですが、 fumiさんのおっしゃる Remove に盞圓するのは Without ず呌んでいたす。
型族っおカリヌ化みたいなのできたっけ
っぜいこずが曞いおある
http://www.kotha.net/ghcguide_ja/latest/type-families.html#type-family-declarations
僕はあんたり詳しく無いですが、確かこの論文に色々曞いおあったような
Promoting Functions to Type Families in Haskell
https://repository.brynmawr.edu/cgi/viewcontent.cgi?referer=&httpsredir=1&article=1000&context=compsci_pubs
型族は垞に匕数を飜和させる必芁がありたす。゚レガントさは損なわれたすが、Withoutは盎接定矩するこずになるず思いたす
@kaznak has joined the channel
毎床ありがずうございたす。
「レコヌドから指定したキヌの芁玠を取り陀いたレコヌドを返す関数」䜜りの続きです。
:point_down: のような、closedな型族ず型クラスを組み合わせお、レコヌドが空の堎合ずそうでない堎合ずで実装をわけられるようにしたした。
が、残念ながら今床は実装で思わぬコンパむル゚ラヌになっおしたいたす゚ラヌメッセヌゞは埌ほどコメントに匵りたす
おそらくもう䞀歩なずころだず思うので、助蚀をいただきたく
type family Result (x :: k) (xs :: [k]) :: [k] where
  Result x '[] = '[]
  Result x (x ': xs) = Result x xs
  Result x (y ': ys) = y ': Result x ys

class Without (x :: k) (xs :: [k]) where
  without :: Membership xs x -> (h :* xs) -> (h :* Result x xs)

instance Without x '[] where
  without _ _ = nil

instance Without x (x ': xs) where
  without key rec =
    let (_, ys) = huncons $ toHList rec
    in without key (fromHList ys)

instance Without x (y ': ys) where
  without key rec =
    let (y, ys) = huncons $ toHList rec
    in y <: without key (fromHList ys)

huncons :: HList h (x ': xs) -> (h x, HList h xs)
huncons (HCons hx hxs) = (hx, hxs)
゚ラヌメッセヌゞです :point_down:
app\Main.hs:41:21: error:
    ? Couldn't match type ‘xs’ with ‘x : xs’
      ‘xs’ is a rigid type variable bound by
        the instance declaration at app\Main.hs:38:10-28
      Expected type: h :* (x : xs)
        Actual type: h :* xs
    ? In the second argument of ‘without’, namely ‘(fromHList ys)’
      In the expression: without key (fromHList ys)
      In the expression:
        let (_, ys) = huncons $ toHList rec in without key (fromHList ys)
    ? Relevant bindings include
        ys :: HList h xs (bound at app\Main.hs:40:13)
        rec :: h :* (x : xs) (bound at app\Main.hs:39:15)
        key :: Membership (x : xs) x (bound at app\Main.hs:39:11)
        without :: Membership (x : xs) x
                   -> (h :* (x : xs)) -> h :* Result x (x : xs)
          (bound at app\Main.hs:39:3)
   |
41 |     in without key (fromHList ys)
   |                     ^^^^^^^^^^^^

app\Main.hs:46:26: error:
    ? Couldn't match type ‘ys’ with ‘y : ys’
      ‘ys’ is a rigid type variable bound by
        the instance declaration at app\Main.hs:43:10-28
      Expected type: h :* (y : ys)
        Actual type: h :* ys
    ? In the second argument of ‘without’, namely ‘(fromHList ys)’
      In the second argument of ‘(<:)’, namely
        ‘without key (fromHList ys)’
      In the expression: y <: without key (fromHList ys)
    ? Relevant bindings include
        y :: h y (bound at app\Main.hs:45:10)
        ys :: HList h ys (bound at app\Main.hs:45:13)
        rec :: h :* (y : ys) (bound at app\Main.hs:44:15)
        key :: Membership (y : ys) x (bound at app\Main.hs:44:11)
        without :: Membership (y : ys) x
                   -> (h :* (y : ys)) -> h :* Result x (y : ys)
          (bound at app\Main.hs:44:3)
   |
46 |     in y <: without key (fromHList ys)
質問がありたす。

緎習のために、 stack resolver lts-11.9 の環境で数独に関するラむブラリを䜜っおいたす。
いた、䞀぀のセルの状態を衚珟するために Maybe を䜿おうず思っおたす。
䟋えば、あるセルに 1 が入っおいれば Maybe 1 、空ならば Nothing ずいう具合です。

ただ、そのたたでは show した時に Maybe や Nothing が衚瀺されおしたうので、
この衚瀺を倉えたいず思っおいたす。
䟋えば、 Maybe 1 ならば 1 、 Nothing ならば _ が出力されるずいう具合にです。
出来れば read も同じように出来るず嬉しいです。

Maybe 関連のラむブラリ関数を䜿いたいので、さしあたっお show ず read の振る舞いだけ倉えたいのです。
こういった、ほずんど同じなんだけど、ほんの少し振る舞いが異なる型を衚珟したいずきはどうしたら良いのでしょうか。

よろしくお願いしたす。
newtype Cell = Cell (Maybe Int)

ですねぱっず思い぀くのは。

newtype ずするこずで、 Cell はたさにおっしゃるような、 「 Maybe Int ず ほずんど同じなんだけど、ほんの少し振る舞いが異なる型」ずしお定矩できたす。
ただ、個人的には Show はあくたでもデバッグ甚の文字列に倉換するものずしお䜿ったほうがよいのではないかず考えおいたす。
なので、 newtype でセル専甚の型を甚意するにせよしないにせよ、
Show や Read のむンスタンスを無理に曞き換えずに、文字列からパヌスしお䜜成したり文字列に倉換する甚の関数は独立しお䜜った方がいいんじゃないかず思いたす。
あんたりよくわかっおないですが
instance Without x ys => Without x (y:ys) where

が正しいのではないでしょうか(Overlappingしそうですが)
prettyprinter https://hackage.haskell.org/package/prettyprinter は、名前の通りShowよりも小奇麗に衚瀺するのに適しおいたす。敎列衚瀺などもできるのでお詊しあれ
@igrep pinned a message to this channel.
文脈を把握しおきたんですけどうヌん僕はあたり型レベルプログラミングには詳しくないんですがhFilterは結構実装難しいんじゃないんですかね䞊の゚ラヌは`Without x xs =>` の制玄がないためxsに察しおxのwithoutメ゜ッドを呌べない゚ラヌですがおそらく呌べるようにしおみおも
type family Result (x :: k) (xs :: [k]) :: [k] where
  Result x '[] = '[]
  Result x (x ': xs) = Result x xs
  Result x (y ': ys) = y ': Result x ys

のResult x (y ’: ys)の郚分がかなり怪しくっおこい぀をpolymorphicなたたで呌び出すのはかなり技巧が必芁だず思いたすね
たあ少なくずも䞊の䟋ほど単玔には曞けないんじゃないかなず思いたす(なんらかのtype equalityをラップする凊理が必芁なんじゃないかなず思いたす)
ありがずうございたす。newtype 䜿うずいい感じに曞けたした。

ただ、個人的には Show はあくたでもデバッグ甚の文字列に倉換するものずしお䜿ったほうがよいのではないかず考えおいたす。

これはなぜなんですかね? なんずなく Show や Read は暙準のリヌダ/ラむタなのかなず思っおいたのですが。

prettyprinter ありがずうございたす。芋おみたす。
なんか知識が錆び぀いおたみたいですね昔は䞀苊劎必芁だった気がするんですが https://hackage.haskell.org/package/base-4.10.1.0/docs/Data-Type-Equality.html#t:-61--61- を䜿えば結構簡単にいけたしたねFunctionalDependenciesを䜿うずいけるず思いたす(HListがその方匏っぜいですね)
いちよ曞いたや぀を眮いずきたす(ただHListを参考にやっお芋た方が分かりやすいかもしれたせんあずextensibleよく知らないんですがMembershipが内郚で持っおる䜍眮をfilter埌に移しおやる必芁があったりするんじゃないんですかね)
https://gist.github.com/mizunashi-mana/df1d54e87a9901b9f225f1ed658bdff6
コヌドがちょっずミスっおたんで埮修正したした
絶察にそうした方がいいずいう぀もりではないですが、
䟋えば String の show 関数は、受け取った文字列をそのたた返すのではなく、
ダブルクォヌトで囲ったり、゚スケヌプシヌケンスがわかりやすくなるように倉換したりしお返すようになっおいたす。
これず同じように、倧抂の Show のむンスタンスは、
倉換埌の文字列から、䜕の型の倀を倉換したかがわかりやすいように䜜られおいたす。
traceShowId など Show のむンスタンスをデバッグ甚に䜿う関数に枡しお衚瀺させた際、特に䜕カ所も出力させた堎合にどの型の倀を出力したのか区別できるようにした方が、芖認性が䞊がるためでしょう。
なので、自前で定矩するにしおも、䜕の型の倀から倉換された文字列かがわかりやすいように䜜った方がよいかず思いたす。
なるほど。 Show ず Read はあくたで ghci 甚だず考えたほうが良いっおこずですね。確かにそんな気がしおきたした。ありがずうございたす。
Readを自前実装しようずするずその型のリストをRead察応させるのがめっちゃ面倒ずいう問題もありたす
そうなんですよねぇ。
ただ、おそらく今回のように1アプリケヌションでしか䜿わないデヌタ型であれば、あえお Read のむンスタンスにする必芁はないだろうな、ず思っお觊れおたせんでした。
ラむフゲヌムを䜜りたいんですが、そのためのGUIラむブラリでいいものはありたすか
僕はglossをよく䜿っおたす

ラむフゲヌムならこの simulate っお関数を䜿えば楜に実装できるんじゃないかなず思いたす~!
早い返信ありがずうございたす想定しおいる機胜は停止/再開ボタンずクリックによるセルの反転が含たれおいるので すが、それもたた play で実珟できそうですね
はい、playで実珟できるず思いたす :raised_hands:
glossを䟝存関係に加えた埌にビルドしようずしたら、freeglutをむンストヌルしおいなかったために掚移䟝存関係によるGLUTのビルド時に䜕かが壊れたようで、precompiled packageが党郚読み蟌めなくなったみたいです。
glossを䟝存関係に加えたプロゞェクトをstack buildでビルドした埌に実行しようずしたらuser error (unknown GLUT entry glutInit)が出たため調べたらglutのむンストヌルがいるよず出たため、䞀旊やめお他のプロゞェクトをstack buildでビルドしようずしたら