picture by ghc
Table of Contents
Learning Haskell
Haskellの本家から、おもしろい学習ページをみつけた。 Learning Haskell
これの、4. Spirals, Snowflakes & Trees: Recursion in Pictures が、今回 のターゲット。下記のお絵書きモジュールを時間をかけて入れておく。
Rasterific: A pure haskell drawing engine.
[sakae@arch pict]$ ls CHANGELOG.md LineGraphics.hs Main.hs pict.cabal [sakae@arch pict]$ cat pict.cabal cabal-version: 2.4 name: pict version: 0.1.0.0 synopsis: pict sample homepage: license: NONE author: sakae maintainer: extra-source-files: CHANGELOG.md library exposed-modules: LineGraphics build-depends: JuicyPixels >= 3.3.8, Rasterific >= 0.7.5.4, base ^>=4.16.4.0 default-language: Haskell2010 executable pict main-is: Main.hs other-modules: LineGraphics build-depends: JuicyPixels >= 3.3.8, Rasterific >= 0.7.5.4, base ^>=4.16.4.0, pict default-language: Haskell2010
[sakae@arch pict]$ cat Main.hs module Main where import Codec.Picture import LineGraphics house :: Path house = [(300, 750), (300, 450), (270, 450), (500, 200), (730, 450), (700, 450), (700, 750)] door :: Path door = [(420, 750), (420, 550), (580, 550), (580, 750)] myhouse = drawPicture 5.0 [(lightgreen, house), (red, door)] main :: IO () main = writePng "my.png" myhouse
[sakae@arch pict]$ cabal build Resolving dependencies... Build profile: -w ghc-9.2.7 -O1 In order, the following will be built (use -v for more details): - pict-0.1.0.0 (lib) (first run) - pict-0.1.0.0 (exe:pict) (first run) Configuring library for pict-0.1.0.0.. Preprocessing library for pict-0.1.0.0.. Building library for pict-0.1.0.0.. [1 of 1] Compiling LineGraphics ( LineGraphics.hs, /tmp/pict/dist-newstyle/build/x86_64-linux/ghc-9.2.7/pict-0.1.0.0/build/LineGraphics.o, /tmp/pict/dist-newstyle/build/x86_64-linux/ghc-9.2.7/pict-0.1.0.0/build/LineGraphics.dyn_o ) Configuring executable 'pict' for pict-0.1.0.0.. Preprocessing executable 'pict' for pict-0.1.0.0.. Building executable 'pict' for pict-0.1.0.0.. [1 of 2] Compiling LineGraphics ( LineGraphics.hs, /tmp/pict/dist-newstyle/build/x86_64-linux/ghc-9.2.7/pict-0.1.0.0/x/pict/build/pict/pict-tmp/LineGraphics.o ) [2 of 2] Compiling Main ( Main.hs, /tmp/pict/dist-newstyle/build/x86_64-linux/ghc-9.2.7/pict-0.1.0.0/x/pict/build/pict/pict-tmp/Main.o ) Linking /tmp/pict/dist-newstyle/build/x86_64-linux/ghc-9.2.7/pict-0.1.0.0/x/pict/build/pict/pict ... [sakae@arch pict]$ cabal run Up to date [sakae@arch pict]$ ls CHANGELOG.md dist-newstyle/ LineGraphics.hs Main.hs my.png pict.cabal
普通にghciを起動してしまうと、下記の様に面倒な事になる。必ず、cabal replで起動しよう。
[sakae@arch pict]$ ghci Loaded package environment from /home/sakae/.ghc/x86_64-linux-9.2.7/environments/default GHCi, version 9.2.7: https://www.haskell.org/ghc/ :? for help ghci> :l Main.hs [1 of 2] Compiling LineGraphics ( LineGraphics.hs, interpreted ) LineGraphics.hs:12:1: error: Could not load module ‘Codec.Picture’ It is a member of the hidden package ‘JuicyPixels-3.3.8’. You can run ‘:set -package JuicyPixels’ to expose it. (Note: this unloads all the modules in the current scope.) It is a member of the hidden package ‘JuicyPixels-3.3.8’. You can run ‘:set -package JuicyPixels’ to expose it. (Note: this unloads all the modules in the current scope.) Use -v (or `:set -v` in ghci) to see a list of the files searched for. | 12 | import Codec.Picture | ^^^^^^^^^^^^^^^^^^^^ Failed, no modules loaded. ghci> :set -package JuicyPixels package flags have changed, resetting and loading new packages... ghci> :l Main.hs [1 of 2] Compiling LineGraphics ( LineGraphics.hs, interpreted ) [2 of 2] Compiling Main ( Main.hs, interpreted ) Ok, two modules loaded. ghci> :t drawPicture drawPicture :: Float -> Picture -> Image PixelRGBA8
enjoy
cabal buildしてライブラリィーなパッケージを作成。仕様は、
library exposed-modules: Pict, LineGraphics build-depends: base ^>=4.16.4.0, JuicyPixels >= 3.3.8, Rasterific >= 0.7.5.4
こんな感じ。オリジナルでは、Fractalsとなってたけど、Pictに変更してる。 一番最初に記述したライブラリィーが親分になって、:browseに出てくるよう だ。もう一方も参照(:t xx)できるようにするには、:m + LineGraphicsってやれ ば良い。
sakae@deb:/tmp/pict$ cabal repl Build profile: -w ghc-9.2.7 -O1 In order, the following will be built (use -v for more details): - pict-0.1.0.0 (lib) (ephemeral targets) Preprocessing library for pict-0.1.0.0.. GHCi, version 9.2.7: https://www.haskell.org/ghc/ :? for help [1 of 2] Compiling LineGraphics ( LineGraphics.hs, interpreted ) [2 of 2] Compiling Pict ( Pict.hs, interpreted ) Ok, two modules loaded. ghci> :bro house :: Path door :: Path myhouse :: Image PixelRGBA8 startLineFrom :: Point -> Line -> Line connectLine :: Line -> Line -> Line scaleLine :: Float -> Line -> Line rotateLine :: Float -> Line -> Line fade :: Colour -> Colour spiralRays :: Float -> Float -> Int -> Colour -> Line -> Picture spiral :: Float -> Float -> Int -> Line -> Path polygon :: Int -> Line -> Path kochFlake :: Int -> Line -> Path kochLine :: Int -> Point -> Point -> Path fractalTree :: Float -> Int -> Line -> Path ghci> ghci> :t drawPicture drawPicture :: Float -> Picture -> Image PixelRGBA8 ghci> :t writePng writePng :: PngSavable pixel => FilePath -> Image pixel -> IO () ghci> writePng "a.png" $ drawPicture 3.0 $ spiralRays 1.0 0.95 128 green ((400,400), (400,500)) ghci> hp = pi / 2 ghci> hp 1.5707963267948966 -- 90 degree ghci> ps = spiral hp 1.01 128 ((400,400), (400, 500)) ghci> length ps 128 ghci> take 4 ps [(400.0,400.0),(400.0,500.0),(299.0,500.0),(299.0,397.99)] ghci> take 4 $ drop 64 ps [(444.52094,355.91992),(444.52094,544.9662),(253.58423,544.9662),(253.58423,352.12012)] ghci> writePng "b.png" $ drawPicture 1.0 [(green, ps)]
フラクタルツリーの例。
myline = ((470,800), (360,800)) pp = fractalTree 0.35 13 myline writePng "dol.png" $ drawPicture 2.0 [(green, pp)]
svg
svgはどうかと、haskell専用の羂索サイトで探してみる。
Hackage: The Haskell Package Repository – Search package
何はなくとも、パッケージの体裁を準備。肝心の中身はgitの例。FreeBSDの cabalだと微妙に版が進んだものを提示してきた。cabalは変化が激しくて、ネッ トの情報をそのまま鵜呑みに出来ない。手探りですな。
[sakae@fb /tmp/hoge]$ cat hoge.cabal cabal-version: 3.0 name: hoge version: 0.1.0.0 -- synopsis: -- description: license: Apache-2.0 license-file: LICENSE -- author: -- maintainer: -- copyright: build-type: Simple extra-doc-files: CHANGELOG.md -- extra-source-files: common warnings ghc-options: -Wall executable hoge import: warnings main-is: Main.hs -- other-modules: -- other-extensions: build-depends: base ^>=4.16.4.0, svg-builder hs-source-dirs: app default-language: Haskell2010
裸のghciを使うと、ちょっと嫌味を言われる。cabal replするかemacsから使 え。要するに、xxx.cabalはMakefileなんだな。これに従って、各種のアプリ が動くようになってるって事だ。
ghci> :set -package base package flags have changed, resetting and loading new packages... ghci> :l app/Main.hs [1 of 1] Compiling Main ( app/Main.hs, interpreted ) Ok, one module loaded. ghci> main <?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg xmlns="http://www.w3.org/2000/svg" width="300" xmlns:xlink="http://www.w3.org/1999/xlink" height="200" version="1.11.1"><rect fill="red" width="100%" height="100%"/><circle fill="green" cy="100" cx="150" r="80"/><text fill="white" x="150" font-size="60" y="125" text-anchor="middle">SVG</text></svg>
others
もう少しお絵書きモードを探してみる。
Haskell組み込みDSLでSVGを書く うーん FreeBSD では、コンパイルに失敗 するぞ。
diagrams – svg ? 巨大すぎるパッケージだなあ。
glossではじめるグラフィック描画 これも巨大。OpenGLだかを使うなんて、失 敗にまっしくらっぽい。
ちょいと気分転換に、 ウォークスルー Haskell see monad
xx.cabalで手抜きする方法、みみっちいな。
common shared-properties default-language: Haskell2010 build-depends: -- list of common dependencies library import: shared-properties test-suite start-haskell-test import: shared-properties build-depends: -- list of test only dependencies
Haskell/GHC symbol search cheatsheet これは、ありがたい。記号って大変 だからね。
haddocs by w3m
haskell-modeにw3mとの連携が出てたので、試してみる。
15 Browsing Haddocks using w3m
;; (setq w3m-mode-map (make-sparse-keymap)) ;; (define-key w3m-mode-map (kbd "RET") 'w3m-view-this-url) ;; (define-key w3m-mode-map (kbd "q") 'bury-buffer) ;; ;(define-key w3m-mode-map (kbd "<mouse-1>") 'w3m-maybe-url) ;; (define-key w3m-mode-map [f5] 'w3m-reload-this-page) ;; (define-key w3m-mode-map (kbd "C-c C-d") 'haskell-w3m-open-haddock) ;; (define-key w3m-mode-map (kbd "M-<left>") 'w3m-view-previous-page) ;; (define-key w3m-mode-map (kbd "M-<right>") 'w3m-view-next-page) ;; (define-key w3m-mode-map (kbd "M-.") 'w3m-haddock-find-tag) (defun w3m-maybe-url () (interactive) (if (or (equal '(w3m-anchor) (get-text-property (point) 'face)) (equal '(w3m-arrived-anchor) (get-text-property (point) 'face))) (w3m-view-this-url))) (require 'w3m-haddock) (add-hook 'w3m-display-hook 'w3m-haddock-display) ;; (defcustom haskell-w3m-haddock-dirs ;; '("~/.ghcup/share/doc/")) (define-key haskell-mode-map (kbd "C-c C-d") 'haskell-w3m-open-haddock)
w3m-mode-mapの所が大幅にコメントしてるけど、こうしておかないと、w3mの 閲覧モードが制限されてしまうから。
また、 defcustomをイネーブルにすると、emacsに怒られたので、カスタム設定を個別 にやった。このw3mサポートは、さっぱりメンテナンスされていない。もうw3m なんてのは旧式なUIになったのか。今じゃ、猫も杓子もMS製だものな。
https://hoogle.haskell.org/?hoogle=Graphics.Rasterific
なんてのに一発で飛んで行くようにしたいな。
engine-mode こういう汎用品が有るなあ。
GHCi + Hoogle - A Guide and Thoughts ここまで、やるか? 単独コマンドの hoogleを入れるってか、コンパイルするの非常に大変そう。まあ、裏で秘密の HTTP通信をやる、アプリだからなあ。それに加えてデータベースへのアクセス もある。例えると、mysqlのクライアントだな。ArchLinuxにはコマンドが用意 されてたけど、下記で凌ぐ事にした。
;; engine-mode (require 'engine-mode) (engine-mode t) (setq engine/browser-function 'eww-browse-url) ;; C-x / h (defengine hoogle "https://hoogle.haskell.org/?hoogle=%s" :keybinding "h") ;; C-x / g (defengine google "https://www.google.com/search?ie=utf-8&oe=utf-8&q=%s" :keybinding "g")
検索文字列にカーソルを置いて、 C-x / h すれば、hoogleに飛んでくれる。おしい事に、ドットで結合されたモ ジュール名は、最左しか拾ってくれないので、適当に補ってあげる必要がある。 まあ、それぐらいは我慢しろ。ついでなんで、ググル用も用意した。
Search Hoogle (main): String -> [String] Search Hoogle: a -> [a] Search Hoogle (putStrLn):
とかが、簡単に調べられる。
ググルへの質問
Search Google: haskell ghci no need let ------ haskell ghci no need let - Google 検索: https://www.google.com/search?q=haskell+ Google haskell ghci no need let Submit すべて動画画像ニュース 地図 ショッピング 書籍 検索ツール ヒント: 日本語の検索結果のみ表示します。検索言語は [表示設定] で指定できます 5. GHCi を使う — Glasgow Haskell Compiler 8.2.2 User's Guide ghcguide.haskell.jp › users_guide › ghci GHC 8.0.1 以降 let 文を使わなくても,値や関数で名前を束縛できます. ... HaskellのソースファイルをGHCiにロードするには :load コマンドを使います. GHCi "let" -- what does it do? - haskell - Stack Overflow :
letは必須だと思っていたんだけど、ある時にそれを忘れてしまった。けど、 エラーにならず。なら楽な方が良いと思っていた。これで、お墨つきを得たな。
rust basic
ちょいと浮気して見てる。何となくhaskellの一般系に思えるぞ。 それより、楽しいH本を再読するのが先だな。なんか、螺旋状に理解が深まっ ていく感じがする。
haskellもrustで書いたら、より安全になるだろう。誰かやってみ。 型安全だけじゃ、片手落ちと思うぞ。