haskell-language-server の設定2
https://n314.hatenablog.com/entry/2021/07/24/173834 の続き。
「emacs lsp-mode "disconnected"」で検索した https://github.com/emacs-lsp/lsp-mode/issues/905 ここのコメントに M-x lsp してログを見ろと書いていたので、そのようにする。
lsp-haskell stack "Cradle requires ghc but couldn't find it"
という警告が出ていた。
というかそもそもEmacs起動時に
Server lsp-haskell:27768/starting exited with status exit(check corresponding stderr buffer for details). Do you want to restart it? (y or n)
というエラーも出ていた。
検索して出てきた
haskell-language-server+emacsでのハマりどころ2020年夏
このページを見てもよく分からなかったけど、そういえば hie.yaml が必要だったとどこかに書いていた記憶がある。
手動で作ってうまくいかなくて消したんだった。
hie.yamlでもう一度調べる。
(廃止) VS Code と haskell-ide-engine で Haskell 開発環境を構築する
Haskell環境構築2020簡易版 (macOS, Linux向け) - LugendrePublic
stack install implicit-hie gen-hie > hie.yaml
そして stackプロジェクトのMain.hsを起動。
emacs app/Main.hs &
おおお、いけたじゃん!
あとは修正と設定。
Error running timer ‘lsp--on-idle’: (wrong-type-argument integerp 9.223372036854776e+18)
というエラーが出るのを回避する。
https://github.com/emacs-lsp/lsp-mode/issues/2435
(setq lsp-headerline-breadcrumb-enable nil)
Error while checking syntax automatically: (error "Keyword argument :end-line not one of (:buffer :checker :filename :line :column :message :level :id :group)")
というエラーが出るのでflycheckをバージョンアップ。
型を自動で挿入したいので
(defun lsp-haskell-execute-code-action-add-signature () "Execute code action of add signature. Add the type signature that GHC infers to the function located below the point." (interactive) (let ((action (seq-find (lambda (e) (string-prefix-p "add signature" (lsp:code-action-title e))) (lsp-code-actions-at-point)))) (if action (lsp-execute-code-action action) (message "I can't find add signature action for this point"))))https://www.ncaq.net/2021/06/25/18/20/30/
これを何かのキーに割り当てる。
オプションで
{-# OPTIONS_GHC -Wmissing-signatures #-}
を設定してwarningが出るようにしておく必要があるっぽい。
あとは定義ジャンプ。
Emacs で Language Server Protocol を使ってみる :: プログラマになりたい人生 — プログラマになりたいおじさんの日記
右に色々出たりコードに線が出るけど、まだあまり意味が分かっていない。
Fold とか Unfold は何なんだろう…?IDEで関数を閉じたりする?haskell-modeでは使わない?
Use pointとかreduceとかは押したら文字が削られる…。
How do you use (un)folding? · Issue #418 · haskell/haskell-language-server · GitHub
よく分からん…。
他にも、haskellではなくてlsp-modeのreadmeを見た方がいいかも。
7/31 追記:
Main.hs is not part of any project. Select action: i==>Import project root path/to/project/ I==>Import project by selecting root directory interactively. d==>Do not ask again for the current project by adding /path/to/project to lsp-session-folders-blacklist D==>Do not ask again for the current project by selecting ignore path interactively. n==>Do nothing: ask again when opening other files from the current project.
というメッセージがミニバッファに出る場合は i を押す。
一瞬で消えたりするので、他のキーを触らずに i を押す。M-x lsp でもう一度見れる。
もしかして以前やったときはこのメッセージを見逃していたのかもしれない。
あと、他のファイルに飛べない?
xref-find-definitions で Main.hs から Lib.hs に飛べない。
と思ったけど、Lib.hs と同じ階層にFoo.hsを作ったらそこには飛べる。
stack new したプロジェクトの構成が分かってないのが問題か…。
Haskellのstackによるプロジェクトについて - Qiita
コメントも参考になる。
Stackでやる最速Haskell Hello world! (GHCのインストール付き!) - Qiita
チュートリアル。
Emacsのplantuml-modeのpreviewで日本語が文字化け
別のPCで設定したらPlantUMLのプレビューで日本語が出なくなっていて、放置していた。
コマンドなら問題なかったので、Emacsがどういうコマンドオプションで呼び出しているのかをシェルスクリプトでprint debugして調べて、手動で実行してみる。
cat foo.plantuml | /path/to/bin/plantuml -headless -tsvg -p > foo.svg
svgに問題はなかった。
でもこのsvgをEmacsで開くと文字化けする。
Emacsのimage-modeの設定?
昔の環境だとsvgではなくpngでプレビューしてたのかな。
どこかに設定があるはずだと思って設定方法を探す。
GitHub - skuro/plantuml-mode: A major mode for editing PlantUML sources in Emacs
よく分からんかったのでplantuml-mode.el のソースを見て調べた。
(setq plantuml-output-type "png")
これでプレビューの日本語が出るようになった。
関数型プログラミングの考え方を理解するための昔の記事
この前
関数型プログラミングはまずは純粋関数型言語を用いて、考え方から理解しよう
関数型プログラミングはまず考え方から理解しよう - Qiita
ここを読んだ。
関数型プログラミングの考えを学ぶには、純粋関数型言語で学ぶべきである
これは同意なんだけど、サンプルコードがしっくり来ない。
こんなに複雑になる?というかオブジェクト指向のコードを関数型っぽく変換ということに無理があるような。
仕様を満たすコードをゼロから考えたら、全然変わってくるような。
ということでちょっとHaskellで書いてみた。
data Dish = Karaage deriving Eq data Bento = Bento Dish Int deriving Eq
単純な数値のリストかタプルでもいいんだけど、オブジェクト指向に寄せてデータ構造を書く。
eat :: Bento -> Bento eat (Bento s a) = Bento s (a - 1) replaceList :: Bento -> [Bento] -> [Bento] replaceList m a = replace a where replace [] = [] replace (x:xs) | m == x = eat x:xs | otherwise = x:replace xs
「データを1減らす」という処理と「リストを一つ入れ替える」という処理を書く。
「リストから最大のものを1件探す」という処理は maximumが使えるので、そのまま使う。
それからユーティリティ的な関数、「xに関数fをn回適用した結果を返す」を作る。
nest :: (a -> a) -> a -> Int -> a nest f x n = (iterate f x) !! n
最後に
bentoList :: [Bento] bentoList = [Bento Karaage 10, Bento Karaage 8, Bento Karaage 6] main :: IO () main = putStrLn $ show $ nest (maximum >>= replaceList) bentoList 5
一気に関数を接続して、計算。
※ n回繰り返したときの処理ログが欲しいわけではなく、最後の結果が欲しいということだと読み取ったので、途中経過は出力しない。
関数型プログラミングっていうかHaskell独自のことかもしれないけど、とりあえず細かい関数のパーツを作っておいて、繋ぎ合わせて大きな機能を作るのが関数型プログラミングの考え方っぽいと思える。
昔見たブログのやり取りはとても良かった。
Haskell でグローバル変数が欲しい理由 - あどけない話
グローバル変数が欲しい理由? (http://web.archive.org/web/20100702191552/http://www.sampou.org/cgi-bin/haskell.cgi?%A5%B0%A5%ED%A1%BC%A5%D0%A5%EB%CA%D1%BF%F4%A4%AC%CD%DF%A4%B7%A4%A4%CD%FD%CD%B3%A1%A9 )
「グローバル変数が欲しい理由?」の考察 - あどけない話
URLが変わっちゃったので再度メモ。
以下全体のコード。
module Main where data Dish = Karaage deriving Eq data Bento = Bento Dish Int deriving Eq instance Show Dish where show Karaage = "唐揚げ" instance Show Bento where show (Bento a b) = show a ++ show b ++ "個" instance Ord Bento where compare (Bento Karaage a) (Bento Karaage a') = compare a a' nest :: (a -> a) -> a -> Int -> a nest f x n = (iterate f x) !! n eat :: Bento -> Bento eat (Bento s a) = Bento s (a - 1) replaceList :: Bento -> [Bento] -> [Bento] replaceList m a = replace a where replace [] = [] replace (x:xs) | m == x = eat x:xs | otherwise = x:replace xs bentoList :: [Bento] bentoList = [Bento Karaage 10, Bento Karaage 8, Bento Karaage 6] main :: IO () main = putStrLn $ show $ nest (maximum >>= replaceList) bentoList 5
haskell-language-server の設定の途中
https://n314.hatenablog.com/entry/2021/07/20/203555 の続き。
https://haskell.e-bigmoon.com/hie/emacs.html
https://haskell.e-bigmoon.com/posts/2020/07-12-haskell-language-server.html
git clone https://github.com/haskell/haskell-language-server.git cd haskell-language-server # stack ./install.hs hls stack ./install.hs hls-8.10.4
GHCバージョンが新しくなりすぎないように、バージョンを指定する。stack ./install.hs help で見れる。
8.10.4 は resolver: lts-17.12 ?
emacsのパッケージでエラーが出るので
https://github.com/emacs-lsp/lsp-java/issues/142
ここに書いている通り
("gnu" . "http://elpa.gnu.org/packages/")
を加える。
melpa の stable は除外した。
package-install でlsp-mode、lsp-ui、lsp-haskellをインストール。エラーが出るので dash も入れる(更新?)。
C-c C-l でstackを使う設定。
https://qiita.com/t-mochizuki/items/d831df3a920108e2d83c
~/.stack/config.yaml に allow-newer: true を付けて stack install cabal-install する。
・・・
最新版で入れ直したり色々やったけど、LSP[Disconnected] になってる。
うーん分からん…。
とりあえず、エラーは出るしC-c C-l も出来るようになったんだけど、型注釈の補完ができない。あとエラーをいい感じに表示する方法が分からない。
これはlsp-haskellで調べずに、lsp-mode とかで調べないといけないのかな。
Googleアナリティクス4プロパティで使われているフロントエンドのツール
メインのプログラムは<script id=base-js ・・・となっている場所にある。
あとはHTMLやJSのcopyrightなどを見ていく。
依存関係は知らないので(angularを使えばlessとmaterialは勝手に付いてくるよ!など)見つけた順に書いていく。
- Closure Library
- Closure Compiler
- Less 1.7.5 https://lesscss.org/
- Material Design https://material.io/
- jQuery 2.2.5-pre
- AnglarJS 1.6.4 https://angular.io/
- d3 https://github.com/d3/d3
- Papa Parse 4.1.2
- RxJS
- MochiKit (Closure Library)
- Polymer https://github.com/Polymer/polymer (?)
- Math.uuid.js 本家消滅? https://gist.github.com/Wind4/3baa40b26b89b686e4f2
- https://fonts.google.com/
今までと大きな違いは無い感じ。
Angular用の細かいライブラリは省略。
StackでHaskellの環境を作れなかったログ
今のPCにGHCが無かったので入れた。
どうやって環境を作ったのか忘れていて、どこかに書いた気がするけど見つからないのでメモ。
うーん…stackの一通りの使い方とか、前にも書いた気がするんだが…。GHCJSのことを書いて肝心のGHCのことは書いてなかった?
sudo apt-get install g++ gcc libc6-dev libffi-dev libgmp-dev make xz-utils zlib1g-dev git gnupg netbasehttps://docs.haskellstack.org/en/stable/install_and_upgrade/#linux
今の環境だと全てインストールされていたので実行する必要はなかった。無い場合は入れる。
https://get.haskellstack.org/stable/linux-x86_64.tar.gz
バイナリを取ってきて ~/bin/ 等にコピー。
最初のhello worldを実行。
stack new helloworld new-template cd helloworld stack build
まだ環境が何もないのでダウンロードが始まる。 ~/.stack/ に環境が作られる。
ghc-modをインストール。
stack install ghc-mod
エラーでインストールできない。
Failing to build ghc-mod with stack · Issue #940 · DanielG/ghc-mod · GitHub
~/.stack/global-project/stack.yaml でLTSのバージョンを変える。
resolver: lts-9.21
ちょっとバージョンが古くなってしまったけれど、これでいけた。
stack install intero
次はintero-modeが動かない。
intero-modeのページにも、別のツールを使えと書いていた。
ghc-modのページにも、古いから haskell-ide-engine を見ろと書いていて、haskell-ide-engine のページには haskell-language-server を見ろと書いていた。カオス。あんまり複雑なのは嫌なんだけど…。
https://n314.hatenablog.com/entry/2019/06/01/191056
ここで色々やったみたい。うーん諦めて新しい方のツールを入れるべきか。
TCPDFで円とベジェ曲線で図形を描く
TCPDFでちょっとした図形を入れたい場合、画像を使わずに直接PDFに出力してしまう方法がある。
TCPDFのソースとマニュアルを見ていたらベジエ曲線が簡単に描けるようなのでやってみた。
(ベジェ曲線?どっち?昔聞いたときはベジエ曲線と発音されていたような気がする。)
まずは円弧を描く。
<?php // (snip) $x = $pdf->GetX(); $y = $pdf->GetY(); $w = 20; $h = 20; $cx = $x + $w / 2; $cy = $y + $h / 2; $cw = $w / 2; $start = 0; $end = $start + 255; $pdf->Circle($cx, $cy, $cw, $start, $end, 'D');
角度は右が0度で半時計回りに指定するようだ。
これで右から255度分の円弧を描ける。
ベジエ曲線は、開始座標+3座標を指定する。
<?php // (snip) $ax = $cx + $cw * cos(deg2rad($end)); $ay = $cy - $cw * sin(deg2rad($end)); $aw = $x + $w - $ax; $ax1 = $ax + $aw / 2 * $sign; $ax2 = $ax + $aw * $sign; $ax3 = $ax + $aw * $sign; $ay1 = $ay; $ay2 = $ay + $w / 3; $ay3 = $ay + $w / 2.5; $p1 = [$ax1, $ay1, $ax2, $ay2, $ax3, $ay3]; $pdf->Polycurve($ax, $ay, [$p1], 'D');
円弧の端の座標をsinとcosで求める。
角度は$endをラジアンに変換する。deg2radっていう組み込み関数があったんだね。
そこからなめらかになるように、座標を配列で指定して Polycurve 関数で出力する。[$p1]となっているところは、複数繋げると複雑な曲線が描ける。
こんな感じに線を引けた。
中を塗る場合は、反転したベジエ曲線切らずに繋げて空白を埋めるように工夫する必要がある。
<?php require_once 'vendor/autoload.php'; function drawCircle($pdf, $reverse) { $x = $pdf->GetX(); $y = $pdf->GetY(); $w = 20; $h = 20; $cx = $x + $w / 2; $cy = $y + $h / 2; $cw = $w / 2; $start = 0; $end = $start + 255; $pdf->Circle($cx, $cy, $cw, $start, $end, 'D'); } function drawBezier($pdf, $reverse) { $x = $pdf->GetX(); $y = $pdf->GetY(); $w = 20; $h = 20; $cx = $x + $w / 2; $cy = $y + $h / 2; $cw = $w / 2; if (!$reverse){ $start = 0; $end = $start + 255; }else{ $start = 285; $end = 180 + 360; } if (!$reverse){ $sign = 1; $point = $end; }else{ $sign = -1; $point = $start; } $ax = $cx + $cw * cos(deg2rad($point)); $ay = $cy - $cw * sin(deg2rad($point)); if (!$reverse) $aw = $x + $w - $ax; else $aw = $ax - $x; $ax1 = $ax + $aw / 2 * $sign; $ax2 = $ax + $aw * $sign; $ax3 = $ax + $aw * $sign; $ay1 = $ay; $ay2 = $ay + $w / 3; $ay3 = $ay + $w / 2.5; $p1 = [$ax1, $ay1, $ax2, $ay2, $ax3, $ay3]; $pdf->Polycurve($ax, $ay, [$p1], 'D'); } $pdf = new TCPDF(); $pdf->AddPage(); $pdf->SetFont('genshingothic', '', 8); $color = [255,100,100]; $pdf->SetFillColor(...$color); $pdf->SetDrawColor(...$color); $pdf->Cell(0, 0, '円弧を描く', 0, 1); drawCircle($pdf, false); $pdf->SetY($pdf->GetY() + 30); $pdf->Cell(0, 0, '円弧を反転してもう一つ描く', 0, 1); drawCircle($pdf, false); $pdf->SetX($pdf->GetX() + 20); drawCircle($pdf, true); $pdf->SetY($pdf->GetY() + 30); $pdf->Cell(0, 0, 'ベジエ曲線を描く', 0, 1); drawCircle($pdf, false); drawBezier($pdf, false); $pdf->SetY($pdf->GetY() + 30); $pdf->Cell(0, 0, '円弧とベジエ曲線を反転して描く', 0, 1); drawCircle($pdf, false); drawBezier($pdf, false); $pdf->SetX($pdf->GetX() + 20); drawCircle($pdf, true); drawBezier($pdf, true); $pdf->Output();