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 でのデバッグ手法あれこれ

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でも、さりげなく利用 されてます)前回出てきた、永遠に改行しないデー タを整形できるかと思ったんだ。

結論は、綺麗に整形するアプリを実現する為の部品集だった。

Text.PrettyPrint.Leijen 概要

Haskell で Verilog を書く話 (1)

Gauche:PrettyPrint

A prettier printer by haskell

RubyとHaskellによる簡単なCSVファイルの集計

ちょいと悔しいので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」がオープンソースで公開

流行だからなあ。


This year's Index

Home