Exception
Table of Contents
Exception
*** Exception: bb.png: withBinaryFile: does not exist (No such file or directory)
前回こんなエラーを頂いた。そう、頂いたんです。エラーの数だけ強くなれる よって事で、調べてみんしゃいって言う神託ですからね。大事にしましょ。
sakae@deb:~/Trees.hsproj$ cabal build Warning: The package list for 'hackage.haskell.org' is 17 days old. Run 'cabal update' to get the latest list of available packages.
そしてこちらは、haskellさんからのアップデート通知。少しづつ新らしくし ろって事だな。何をしたかったかと言うと、writePngが何処で定義されてるか 調べたかったのさ。
ghci> :i drawPicture drawPicture :: Traversable t => Float -> t PictureObject -> Image PixelRGBA8 -- Defined at ShapeGraphics.hs:111:1 ghci> :i writePng writePng :: PngSavable pixel => FilePath -> Image pixel -> IO () -- Defined in ‘Codec.Picture.Png.Internal.Export’
この方法を思いつけまで、原始的な事をしていた。曰く
sakae@deb:/tmp/Rasterific-0.7.5.4$ cd src/ sakae@deb:/tmp/Rasterific-0.7.5.4/src$ grep writePng -r . ./Graphics/Rasterific.hs:-- > import Codec.Picture( PixelRGBA8( .. ), writePng ) ./Graphics/Rasterific.hs:-- > writePng "yourimage.png" img ./Graphics/Rasterific.hs:-- > import Codec.Picture( PixelRGBA8( .. ), writePng ) ./Graphics/Rasterific.hs:-- > writePng "text_example.png" .
どこから輸入してるかソースレベルで調べてたのさ。これって、ソース嫁って いうOSSの思想だな。まあ、これでもいいんだけど、折角ghciのサービスが有 るんだから、利用しない手はないよ。pythonだと、必ずモジュール名を前置す る事になってて、出身が一発でわかってた。これだと、すぐに調べる場所が特 定できていいなって思ってた。まあ、わずらわしい面もあるけどね。
ここまで分かれば、後はhoogleさんだな。
module Codec.Picture.Png.Internal.Export( PngSavable( .. ) , PngPaletteSaveable( .. ) , writePng , encodeDynamicPng , writeDynamicPng ) where : writePng :: (PngSavable pixel) => FilePath -> Image pixel -> IO () writePng path img = Lb.writeFile path $ encodePng img
で、一生懸命に、Lb.writeFileを探すも見付からず。よく考えたら、Lb. って、 モジュールの接頭語じゃん。
sakae@deb:/tmp/JuicyPixels-3.3.8/src/Codec/Picture$ grep 'as Lb' -r . ./Tiff.hs:import qualified Data.ByteString.Lazy as Lb ./Tga.hs:import qualified Data.ByteString.Lazy as Lb ./Png.hs:import qualified Data.ByteString.Lazy as Lb ./Png/Internal/Export.hs:import qualified Data.ByteString.Lazy as Lb
遅延版の文字列をwriteFileするんだなと理解出来た。段々とこつが掴めてた ぞ。
で、例外になるのは、フォントが導入できなくて、その為に有効なデータを作 成できずに、空文字になってるんではなかろうか? 小さな検証スクリプトを 作成。
module Main where import qualified Data.ByteString.Lazy as BL -- w8 = BL.pack ([65..70] ++ [10]) w8 = BL.empty main = do BL.writeFile "foo.txt" w8
ByteStringな文字列は、配列に格納しておく。そのために、pack関数で登録。 空文字を作成するために、わざわざemptyという関数が用意されている。
λ> :l app/Main.hs [1 of 1] Compiling Main ( app/Main.hs, interpreted ) Ok, one module loaded. λ> w8 "ABCDEF\n" λ> main λ> :r λ> w8 "" λ> main
エラーを期待したんだけど、エラーにはならなかった。エラーを伝達する特別 な方法でも用意されているのだろうか?
Haskell の Text と ByteString 色々あるな。適材適所しろよって事。 Haskellの文字について も参考に。
cabal update
やってみた。
sakae@deb:/tmp/t$ cabal update Downloading the latest package list from hackage.haskell.org Updated package list of hackage.haskell.org to the index-state 2023-05-08T20:25:30Z To revert to previous state run: cabal v2-update 'hackage.haskell.org,2023-04-20T21:55:44Z'
4/20 -> 5/08へと更新された訳ね。そして、その実体は、下記の様だった。
sakae@deb:~/.cabal/packages/hackage.haskell.org$ ls -ltr : drwxr-xr-x 3 sakae sakae 4096 Apr 28 07:25 yaml/ drwxr-xr-x 3 sakae sakae 4096 Apr 28 07:25 hlint/ -rw-r--r-- 1 sakae sakae 4 May 9 05:42 01-index.timestamp -rw-r--r-- 1 sakae sakae 464 May 9 05:42 timestamp.json -rw-r--r-- 1 sakae sakae 970 May 9 05:42 snapshot.json -rw-r--r-- 1 sakae sakae 113528425 May 9 05:42 01-index.tar.gz -rw-r--r-- 1 sakae sakae 849951232 May 9 05:43 01-index.tar -rw-r--r-- 1 sakae sakae 5033794 May 9 05:43 01-index.tar.idx drwxr-xr-x 86 sakae sakae 4096 May 9 05:43 ./ -rw-r--r-- 1 sakae sakae 7299071 May 9 05:43 01-index.cache
sakae@deb:~/.cabal/packages/hackage.haskell.org$ tar tvf 01-index.tar | head -rw-r--r-- IanLynagh/Hackage 779 2006-09-06 08:37 iconv/0.2/iconv.cabal -rw-r--r-- IsaacJones/Hackage 4541 2006-09-25 04:15 Crypto/3.0.3/Crypto.cabal -rw-r--r-- IsaacJones/Hackage 481 2006-09-25 04:15 HDBC/1.0.1/HDBC.cabal -rw-r--r-- IsaacJones/Hackage 704 2006-09-25 04:15 HDBC-odbc/1.0.1.0/HDBC-odbc.cabal -rw-r--r-- IsaacJones/Hackage 757 2006-09-25 04:15 HDBC-postgresql/1.0.1.0/HDBC-postgresql.cabal -rw-r--r-- IsaacJones/Hackage 618 2006-09-25 04:15 HDBC-sqlite3/1.0.1.0/HDBC-sqlite3.cabal -rw-r--r-- IsaacJones/Hackage 376 2006-09-25 04:15 darcs-graph/0.1/darcs-graph.cabal -rw-r--r-- IsaacJones/Hackage 530 2006-09-25 04:15 hask-home/2006.3.23/hask-home.cabal -rw-r--r-- IsaacJones/Hackage 890 2006-09-25 04:15 hmp3/1.1/hmp3.cabal -rw-r--r-- IsaacJones/Hackage 2143 2006-09-25 04:15 lambdabot/4.0/lambdabot.cabal
過去からの遺産の目録が詰っているのか。して、その個数は?
sakae@deb:~/.cabal/packages/hackage.haskell.org$ tar tvf 01-index.tar | wc -l 305652
カタログから選び出した、あれが有るはず。そう、前回お世話になってた writePngとかのモジュールね。ここに入いっているから、わざわざDLしなくて もいいんだな。
sakae@deb:~/.cabal/packages/hackage.haskell.org$ ls -dl J* R* drwxr-xr-x 3 sakae sakae 4096 Apr 26 08:31 JuicyPixels/ drwxr-xr-x 3 sakae sakae 4096 Apr 26 08:31 Rasterific/ sakae@deb:~/.cabal/packages/hackage.haskell.org$ ls -l Rasterific/0.7.5.4/Rasterific-0.7.5.4.tar.gz -rw-r--r-- 1 sakae sakae 827372 Apr 26 08:31 Rasterific/0.7.5.4/Rasterific-0.7.5.4.tar.gz
いやー、つきつめていくと、色々な事がわかってくるね。おまけでtar玉を /tmpに展開してみたら、途中から、DISKが一杯になりましたエラー。おかしい なと思ったら、iノードの方が一杯になってた。こんなエラーは超久しぶり。 newsシステムのフィードを受けてた時以来か。記念の魚拓。
sakae@deb:/tmp$ df /tmp Filesystem 1K-blocks Used Available Use% Mounted on tmpfs 1948076 546768 1401308 29% /tmp sakae@deb:/tmp$ df -i /tmp Filesystem Inodes IUsed IFree IUse% Mounted on tmpfs 192404 192404 0 100% /tmp
make Exception
上のDISKエラーに触発されて、格好よく言うとインスパイアーだな、エラーが 発生しなかった検証コードで無理矢理エラーを発生させてみる。さて、どうし たでしょうか?
λ> main *** Exception: /foo.txt: withBinaryFile: permission denied (Permission denied)
これが一例、この他にもDISK容量をくいつぶすとかあるけどね。書き込み禁止 エリアを指定するのが、一番楽か。
Glasgow Haskell Compiler User's Guide
Haskellプログラムの開発を支援する GHCiデバッガフロントエンド
Haskell アクション 超入門 もやもやが解消されるかな。
こんな楽しい機能を見付けたので、そもそもこの記事を起した発端に戻る。わ ざと、ありえないフォントを設定。そうしておいて、
λ> :break renderTree Breakpoint 0 activated at /tmp/Trees.hsproj/BinTrees.hs:49:19-71 λ> writePng "aa.png" ( drawPicture 3 $ renderTree t3 ) Stopped in Main.renderTree, /tmp/Trees.hsproj/BinTrees.hs:49:19-71 _result :: Picture = _ h :: Float = _ p1 :: Picture = _ w :: Float = _ [/tmp/Trees.hsproj/BinTrees.hs:49:19-71] λ> :list 48 renderTree :: Show a => BinaryTree a -> Picture 49 renderTree tree = movePicture (Vector ((1000 - w)/2) ((1000 - h)/2)) p1 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 50 where
debuggerを発動させる。それから、例外が発生したら止まれと指 示。止ったんで、履歴を確認。
[/tmp/Trees.hsproj/BinTrees.hs:49:19-71] λ> :set -fbreak-on-exception [/tmp/Trees.hsproj/BinTrees.hs:49:19-71] λ> :trace Stopped in <exception thrown>, <unknown> _exception :: e = _ [<unknown>] λ> :hist -1 : font:fontErr (ShapeGraphics.hs:162:32-100) -2 : font:fontErr (ShapeGraphics.hs:162:14-100) -3 : font (ShapeGraphics.hs:(163,8)-(165,23)) -4 : movePoint (ShapeGraphics.hs:169:21-27) : -18 : drawPicture:drawObj (ShapeGraphics.hs:(152,7)-(154,31)) -19 : movePoint (ShapeGraphics.hs:169:4-28) -20 : movePoint (ShapeGraphics.hs:169:4-28) ...
履歴を遡って、ソースを点検。デフォで :histのサイズは20になってるけど、 大きな数値を設定すれば、50ステップまでは表示してくれる。
[<unknown>] λ> :hist 100 : -49 : movePoint (ShapeGraphics.hs:168:21-27) -50 : renderTree:renderTree' (/tmp/Trees/BinTrees.hs:67:24-34) <end of history>
[<unknown>] λ> :back Logged breakpoint at ShapeGraphics.hs:162:32-100 _result :: IO (Either String FontyFruity-0.5.3.5-94b9354b2fbc658faa4d6b3183cfde9a31addc91760cb24557f2bdcaa6e6e337:Graphics.Text.TrueType.FontType.Font) [-1: ShapeGraphics.hs:162:32-100] λ> :list 161 = let 162 fontErr = unsafePerformIO $ loadFontFile "/usr/local/share/fonts/mplus-ipa/fonts/M+1P+IPAG.ttfZZ" ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 163 in case fontErr of
現場に辿りついたぞ。万歳三唱。
λ> :break writeFile Cannot set breakpoint on ‘writeFile’: Module ‘System.IO’ is not interpreted
糠喜びは禁物。こういうシステムよりにはBPを設定できない制限も有るのね。
λ> go t2 Stopped in Main.renderTree, /tmp/Trees/BinTrees.hs:57:19-71 _result :: Picture = _ h :: Float = _ p1 :: Picture = _ w :: Float = _ [/tmp/Trees/BinTrees.hs:57:19-71] λ> :set -fbreak-on-exception [/tmp/Trees/BinTrees.hs:57:19-71] λ> :trace Stopped in <exception thrown>, <unknown> _exception :: e = GHC.Exception.Type.SomeException (GHC.IO.Exception.IOError Nothing GHC.IO.Exception.NoSuchThing ....) [<unknown>] λ> :print _exception _exception = GHC.Exception.Type.SomeException (GHC.IO.Exception.IOError Nothing GHC.IO.Exception.NoSuchThing (_t7::String) "No such file or directory" (Just (Foreign.C.Types.CInt (GHC.Int.I32# 2))) (Just "/usr/share/imlib2/data/fonts/notepad.ttfZZZZ"))
何かの拍子に、詳細な例外情報を補足してくれるなあ。タイミングの問題で、 補足出来たり出来なかったりするのかな?
それから、起動の度に入力するのが面倒な怠慢の人は、こんなファイルを用意 すればいいみたい。なんだけど、emacsからの場合は無視される。プロジェク トdir直下にコピしとけばOK.
[sakae@fb ~]$ cat .ghci :set -fbreak-on-exception :set -fbreak-on-error
:show linker
ちまちまとghciのコロンコマンドを点検してたんだ。そうしたら面白い物を発 見。我乍ら、話題が発散してるとは思っているけど、修行の過程だと思ってく ださい。
話の上手な楽しいH本をやるのもいいけど、11章のファンクターからアプリカ ティブファンクターあたりで、正直な所眠くなる。どんな役に立つねん? 丁度、学生時代に、sin,cos,tanを習ったけど、本当に役にたつの。足し算と かけ算がわかれば十分だろうって気持。そんな訳で内職ですよ。 (注: 本当のおもしろさは、11章からってのは定説です)
λ> :show linker ----- Loader state ----- Pkgs: [bytestring-0.11.4.0, template-haskell, pretty-1.1.3.6, ghc-boot-th-9.2.7, deepseq-1.4.6.1, array-0.5.4.0, base, ghc-bignum, ghc-prim, rts] Objs: [] BCOs: [LinkableM (2023-05-09 06:01:42.716725881 UTC) Main [BCOs [BCO main with 0 lits 2 ptrs, BCO main with 2 lits 2 ptrs, BCO w8 with 2 lits 3 ptrs, BCO $trModule with 1 lits 2 ptrs, BCO $trModule2_r182 with 2 lits 0 ptrs, BCO $trModule4_r184 with 2 lits 0 ptrs] []]]
これ、例の検証コードの結果。これだけのパッケージでghciってか、検証コー ドの環境が構築されてる訳ね。そんじゃ、セカンドオピニオン。
λ> :show linker ----- Loader state ----- Pkgs: [Rasterific-0.7.5.4-db212715e67548e861dcd64af8a293e0dc89ce76c74176006019c7855c297615, vector-algorithms-0.9.0.1-1ed8cd90c58c4403af3c162af52826b1b3870993807ba2b450ff935f56867865, bitvec-1.1.4.0-1cedd7616448a00b3d72dcd604a4501a5f720543dafbce62ce9514707de858ff, : text-1.2.5.0, directory-1.3.6.2, unix-2.7.2.2, time-1.11.1.1, filepath-1.4.2.2, binary-0.8.9.0, containers-0.6.5.1, bytestring-0.11.4.0, template-haskell, pretty-1.1.3.6, ghc-boot-th-9.2.7, deepseq-1.4.6.1, array-0.5.4.0, base, ghc-bignum, ghc-prim, rts] Objs: [] BCOs: []
長いパッケージはオイラーがcabal install Rasterificした奴で、短い物は GHC本舗の規定の奴なんだな。BCOsが [] って事は、アプリじゃないんだな。
λ> :show packages active package flags: -package-id base-4.16.4.0 -package-id Rasterific-0.7.5.4-db212715e67548e861dcd64af8a293e0dc89ce76c74176006019c7855c297615 -package-id JuicyPixels-3.3.8-89fafcb22411fa220d659c0efb61cf7c448bb228ec0601f9de6a8e4e8dd276fa -package-id FontyFruity-0.5.3.5-dd7959c1d89616cbc6b6fff8e7211519dcc9bc060ae096b522dc24ac282b4ba1
これが、*.cabalに記述されたれた、build-depends: って事だな。base -any とかやると、よしなにやってくれるのか。
Prelude
基本を抑えておこうと思い、素のghciでブラウジングしてみた。
[sakae@arch ~]$ ghci Loaded package environment from /home/sakae/.ghc/x86_64-linux-9.2.7/environmens/default GHCi, version 9.2.7: https://www.haskell.org/ghc/ :? for help ghci> :bro (!!) :: [a] -> Int -> a ($) :: (a -> b) -> a -> b : zipWith3 :: (a -> b -> c -> d) -> [a] -> [b] -> [c] -> [d] (||) :: Bool -> Bool -> Bool
330行ぐらい。大事ってか、皆使っていそうなんで、知っておくと吉。
[sakae@arch tmp]$ grep data BRO.log data Bool = False | True data Char = GHC.Types.C# GHC.Prim.Char# data Double = GHC.Types.D# GHC.Prim.Double# data Either a b = Left a | Right b data Float = GHC.Types.F# GHC.Prim.Float# data Int = GHC.Types.I# GHC.Prim.Int# data Integer data Maybe a = Nothing | Just a data Ordering = LT | EQ | GT data Word = GHC.Types.W# GHC.Prim.Word#
こういう見方もあるなあ。後は、classとかtypeとか。classは手抜きしないで、 ちゃんと見ておけ。
hugs98時代のPrelude.hsと比べてみると歴史が知れておもしろい。Functorと Monadしか有りませんでしたとかね。その分シンプル。実装も出ているので、 読むには最適かも。と、逃避モードです。
この世界遺産hugs98は6月にリリースされるDebian 10でも維持されるのだろう か? 是非保存に勤めて欲しいです。
pretty
上でこんなのが出てたので、ひょっとして、gdbでよく使う set print pretty 機能を実現してくれるものかと思った。(:show linkerでも、さりげなく利用 されてます)前回出てきた、永遠に改行しないデー タを整形できるかと思ったんだ。
結論は、綺麗に整形するアプリを実現する為の部品集だった。
ちょいと悔しいのでcabalのカタログのtar玉を展開して、検索してみた。
sakae@deb:~/zzz$ ls -d pretty* pretty/ prettyprinter-combinators/ prettychart/ prettyprinter-compat-annotated-wl-pprint/ pretty-class/ prettyprinter-compat-ansi-wl-pprint/ prettyclass/ prettyprinter-compat-wl-pprint/ pretty-compact/ prettyprinter-convert-ansi-wl-pprint/ pretty-diff/ prettyprinter-graphviz/ pretty-display/ prettyprinter-interp/ pretty-error/ prettyprinter-lucid/ prettyFunctionComposing/ prettyprinter-vty/ pretty-ghci/ pretty-relative-time/ pretty-hex/ pretty-show/ pretty-html/ pretty-show-ansi-wl/ pretty-loc/ pretty-simple/ pretty-ncols/ pretty-sop/ prettyprint-avh4/ pretty-terminal/ prettyprinter/ pretty-tree/ prettyprinter-ansi-terminal/ pretty-types/
同じことをhoogleでは、どうやるのだろう? 中央のドロップダウンリストの 所に、package:prettyと入力すれば、候補がそのドロップダウンに補完された よ。
絞りこんで、pretty-simpleをみると、Text.Pretty.Simple こういうのに行き ついた。これぞ、オイラーの求めていたもの。
tools for working with derived `Show` instances それとも、こちらが手間 いらずに思えるけど、どう使えの案内が無いな。それはコード嫁が解決策。
sakae@deb:~/src/cabal-catlog/Rasterific$ ls 0.1/ 0.4.1/ 0.5.0.3/ 0.6.1/ 0.7.2.2/ 0.7.4.2/ 0.7.5.2/ 0.2/ 0.4.2/ 0.5.1/ 0.6.1.1/ 0.7.2.3/ 0.7.4.3/ 0.7.5.3/ 0.2.1/ 0.5/ 0.5.2/ 0.7/ 0.7.3/ 0.7.4.4/ 0.7.5.4/ 0.3/ 0.5.0.1/ 0.5.2.1/ 0.7.1/ 0.7.4/ 0.7.5/ 0.4/ 0.5.0.2/ 0.6/ 0.7.2.1/ 0.7.4.1/ 0.7.5.1/ sakae@deb:~/src/cabal-catlog/Rasterific$ ls 0.7.5.1 package.json Rasterific.cabal
手元にも残しておくと都合がいいだろうって事で。更に中身を点検。これじゃ、 iノードを消費する訳だ。律儀に履歴を保存してる。何でも、一度アップロー ドした物は削除できない仕様らしい。これぞhaskell流の仕様です。
ChatGPT
このプロンプトエンジニアってAI神に仕える神官か。神からすばらしい緒言を 引き出す能力で尊敬される。現代の いたこ だな。今も恐山におられるのでしょ うか。
超進化したAI「ChatGPT」が生み出す無限のクイズをライブ配信してみた
ブラウザ上で3Dキャラクターと会話できる「ChatVRM」がオープンソースで公開
流行だからなあ。