haskell-jp / questions #54

@misaki has joined the channel
Data.Map型の実装はList Tuple a bを低レイヤーで効率化(btreeに)したもののように見えるのですが,
これをfoldableでパターンマッチングするときに(\acc (a, b) -> --process)というような書き方をMapでできないでしょうか.
@ma.efjay has joined the channel
Mapをキーと値のペアについてfoldしたい、という事ならば、Data.Map.toListで一度リスト化してからfoldするか、またはData.Map.foldlWithKeyなどの関数があるのでこれを使うか、でどうでしょう
ありがとうございます.
やはりそういった方向になるんですね.
今回は[(a, b)]で実装しました.
@a0 has joined the channel
@yuukai.tuukai has joined the channel
stackでbackpackをサポートしてほしいのですが
地道にコマンドを追いかけるしかないですかね
https://github.com/commercialhaskell/stack/issues/2540
作者も忙しそうなので自分で頑張るしかない気がしております
もしかして、 foldrWithKey が相当するものではないでしょうか?
@ue_wo has joined the channel
foldrWithKeyのようです.
ありがとうございます!
@rinseki.contact has joined the channel
Haskellライブラリ公開に向けてのベストプラクティスみたいな記事とかありますか?
自分でライブラリを開発して、最終的にHackageにて公開、逐次バージョンアップデートする方法を紹介してくれるとありがたいです。
日本語記事なかったら書くべき事案っぽい気がしますね(書ける人が
hackage upload とか検索すると、色々出てくる気がするけど
出てくるけど、ベストプラクティスというには程遠いと思う。
http://hackage.haskell.org/upload
理想的には読めばHaskell初心者でも実務で利用可能なライブラリを公開できるような記事が望ましいです。
パッケージのユーザーから見てよいパッケージが何かを知れば、概ねそのまま作る側のベストプラクティスを教えることになるかと思うのですがいかがでしょうか?
(と、自分の記事を推す)
https://wiki.haskell.jp/Hikers%20Guide%20to%20Haskell#%E3%83%91%E3%83%83%E3%82%B1%E3%83%BC%E3%82%B8%E3%81%A8%E3%81%AE%E4%BB%98%E3%81%8D%E5%90%88%E3%81%84%E6%96%B9
最低限cabal sdistコマンドでワーニングが出なければOKだと思います。ただし必要物を.cabalに書き忘れるのは注意っぽい。hpackを使えば自動でファイルリストを書いてくれるのでベター
@takiy33 has joined the channel
@fumieval ありがとうございます!
@hygxsh2k has joined the channel
AWS Lambda上でHaskellを動かす知見をお持ちの方はいらっしゃらないでしょうか・・・

aws-lambda-haskell-runtime(

Serverless Haskell(
を試してみて、単純なサンプルは動作するのですがDynamoDBにアクセスしてみると90秒などという長大な時間がかかってしまい、とても使い物にならないのです。
DynamoDBだけでなくHTTPS通信全般がどうも遅いようで、S3へのアクセスや単なるWebサイトのデータを取ってくるだけでも非常に時間がかかってしまいます。
https全般はtlsがおそいのでopenssl使ってますが、それ以外は気にならないですね
nodeとかでかいたものよりメモリも使わず快適に動いています
haskell-runtimeつかってません。
node.jsからデータを渡してつかっています。
runtimeの問題かもですね。
Travisなどで複数バージョンのGHCに対してテストすると良いと思います https://github.com/haskell-CI/haskell-ci が便利です。
cabal sdist してビルドしたりcabal checkもしてくれるので簡単なミスも気がつけます
@cgp has joined the channel
Either モナドの使い方をお尋ねします。

Eitherを返す複数の関数を組み合わせ Eitherを返す関数を作るとき、組み合わせに含まれるどの関数のLeftで処理が中断されたかわかるようにする方法はありますか?

例えば以下のようなコードがあったとき、
caller x= do
      case someFunc x of
            Left err -> print err
            Right y -> ..

someFunc:: MyType -> Either String OtherType
someFunc mt = do
       first <- SomeEitherFunc mt
       second <- AnotherEitherFunc first
       …


caller 側でLeftを受け取ったとき、 SomeEitherFuncから来たか、AnotherEitherFuncから来たかを区別したいです。
区別する目的は、デバッグや障害時の原因究明で、どこでLeftが発生したかを把握するためです。SomeEitherFunc の Left や、 AnotherEitherFunc の Leftは、どのようなメッセージを持つか事前に分かりません。

     case SomeEitherFunc mt of
          Left err -> Left ( "from SomeEitherFunc:" ++ err)


としていけば目的達成できますが、書き方として冗長な気がするので、別の方法があれば教えていただきたいです。
.o( 何らかソースコードを書き換えないとムリかなぁ
結論から言うと直接実現するのは無理です。
挙げていただいた :point_down: 相当のことを行う、errorsパッケージの Data.EitherR.fmapL 関数を使って頑張るしかないでしょう。
同じような関数はほかのパッケージにもたくさんあるので、探して依存するなりコピペするなりするとよいかと思います。

case SomeEitherFunc mt of

         Left err -> Left ( "from SomeEitherFunc:" ++ err)
デバッグや障害時の原因究明
のためならロガーをしこむのが順当な対応ですかね
someFuncをいじって良いなら、こんな感じに書きます(例として挙がっているやつを関数化しただけ)

haskell
ePrefix :: String -> Either String r -> Either String r
ePrefix pfx (Left orig) = Left (pfx ++ orig)
ePrefix _ r = r

someFunc:: MyType -> Either String OtherType
someFunc mt = do
       first <-  ePrefix "someEitherFunc"    $ someEitherFunc mt
       second <- ePrefix "anotherEitherFunc" $ anotherEitherFunc first
自分ならEither String OtherTypeからEither MyException OtherTypeに変換して、caller側でMyExceptionの値に応じて場合分けするかなー。こんな感じ

caller x= do
      case someFunc x of
            Left err -> print err
            Right y -> print y

type MyType = Int
type OtherType = String

someFunc:: MyType -> Either MyException OtherType
someFunc mt = do
       first <- someEitherFuncWithException mt
       second <- anotherEitherFuncWithException first
       return second
  where
    someEitherFuncWithException = convert SomeEitherError . someEitherFunc
    anotherEitherFuncWithException first = convert AnotherEitherFuncError (anotherEitherFunc first)
    someEitherFunc _    = Left "wrong"
    anotherEitherFunc _ = Right "Correct!"

data MyException = SomeEitherError | AnotherEitherFuncError
    deriving Show

convert :: MyException -> Either String a -> Either MyException a
convert myException (Left _)      = Left myException
convert _           (Right other) = return other
今来ました。こんな風にコールスタックを使うのはいかが?
import GHC.Stack

throw :: HasCallStack => String -> Either (CallStack, String) a
throw msg = Left (popCallStack callStack, msg)

foo :: HasCallStack => Either (CallStack, String) ()
foo = throw "err"

bar :: HasCallStack => Either (CallStack, String) ()
bar = throw "err"

main = case foo >> bar of
  Left (e, msg) -> do
    putStrLn $ prettyCallStack e
    putStrLn msg
  Right a -> print a
実行するとこんな感じで場所がわかります
CallStack (from HasCallStack):
  foo, called at stack.hs:12:13 in main:Main
err
https://github.com/chrisdone/pure-io の代わりになるような、ファイルシステムなどへの読み書きをMonadで簡単にシミュレートするためのパッケージはありませんか?
リポジトリーがすでにarchivedされていることからわかるとおり、もうpure-ioはメンテされていません。
参考までに、pure-ioのドキュメントはこちらです。 http://hackage.haskell.org/package/pure-io-0.2.1/docs/PureIO.html
まぁ、もちろんユースケースに応じて自前で定義すればいいんですけど...
改めて検索してみましたがなさそうなのでこの際自分で作りますね。。。ある程度拡張性も視野に入れつつ、できるだけ単純なものを。
いまいちユーザーケースがわからないのですが、
どういう用途なのでしょうか。
閉鎖された環境はdockerで手に入りますし。
閉鎖された環境が欲しいんじゃなくて、ファイルシステムっぽく振る舞うtest doubleが欲しいのです。
例えば今やりたいのは

readHoge :: Monad m => (FilePath -> m String) -> m String
readHoge readF = do
  hogeContent <- readF "hoge"
  return $ "Hoge: " ++ hogeContent


みたいに、 readFile っぽくふる舞う関数をパラメーターとして受け取れるようにすることで、 IO に依存した処理をテストしやすくする、ということを私はよくやるのですが、その際にテスト用のファイルシステムの実装が必要となるのです。
ちなみに、環境の分離、という意味では https://www.haskell.org/ にある「Try It!」で使用されています。
Dockerよりもお手軽!
なるほど。
https://www.gnu.org/software/libc/manual/html_node/Replacing-malloc.html
LD_PRELOAD
つかうのが簡単ですがそういうのじゃないですよね。
そっすね。あくまでHaskellレベルでお手軽にDIしたいので。(まぁ人によってはそっちの方が簡単に感じるかも知れませんが)
どうせならextensibleとか使ってみてはどうでしょう
@amutake.s has joined the channel
雑に書いてリリースしました。
http://hackage.haskell.org/package/fakefs
extensibleどころかものすごく古典的な書き方で作ってしまいましたが、拡張性の要件は満たせてるはず。。。

ソースはこちら。別件で急いでいるのでドキュメントは後回しにします。あしからず! :sweat_drops:
https://gitlab.com/igrep/haskell-fakefs/blob/master/src/Test/FileSystem/Fake.hs