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

svg-builder

何はなくとも、パッケージの体裁を準備。肝心の中身はgitの例。FreeBSDの cabalだと微妙に版が進んだものを提示してきた。cabalは変化が激しくて、ネッ トの情報をそのまま鵜呑みに出来ない。手探りですな。

第56回 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をやる

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

Rustの基本を解説する『動かして学ぶ!Rust入門』

ちょいと浮気して見てる。何となくhaskellの一般系に思えるぞ。 それより、楽しいH本を再読するのが先だな。なんか、螺旋状に理解が深まっ ていく感じがする。

sudoとsuがRustで書き直される。メモリ安全性向上へ

haskellもrustで書いたら、より安全になるだろう。誰かやってみ。 型安全だけじゃ、片手落ちと思うぞ。


This year's Index

Home