YoshikuniJujo
Haskell好き
YoshikuniJujo
12/15 8:39:39
💕
おはよーございます🦥🫧
⬆
OrzBruford
12/15 8:16:42
💕:ohayou:
nostr:npub1a7y7u324paehw2zdx8jfl3t72ue0ls4etfalxhg0z2gad738savqhxfdm2 おはよ〜💕
YoshikuniJujo
12/13 13:08:26
💕♥ ⭐ 🐾 😐
クロワッサン。
折り込み用のバターは10x10に形を整えた。
焼きは今回は230度5分してホイルを乗せて190度で12分にしてみた。
ホイルを乗せるタイミングを少し遅らせてもいいかも。
YoshikuniJujo
12/13 12:04:39
💕
参照透過性と副作用と純粋さの話、厳密に定義しようとするとわりと微妙なところ出てくる気がする。
三者ともそれぞれに意味合いが違うってのもある。
YoshikuniJujo
12/12 17:53:07
💕
オリジナル版のfoldlは「スペースリークの代表」みたいな関数で、簡単に説明すると、たとえばfoldl (+) 0 [1, 2, 3, 4, 5]というふうに適用した場合に(((((0 + 1) + 2) + 3) + 4) + 5)っていう式ができちゃって、それがそのままサンクとして残るのでメモリーを圧迫するという話。
今のfoldlやfoldl'は毎回サンクをつぶすような実装になってる。
⬆
YoshikuniJujo
12/12 17:49:42
💕 ⭐ 👀 🤙
foldlという関数を見ると、いろいろと話したくなるのがHaskellerの性なのだけど、まあすごく簡単に言うと、「昔はスペースリークの関係でfoldlではなくfoldl'を使えと言われていたけど、今はfoldlとfoldl'は同じものなのでfoldlを使えばいい」という話で、一周して意味のない話になる。
YoshikuniJujo
12/12 17:39:00
💕
検索しやすいように「スリープソート」とつけておく。
⬆
YoshikuniJujo
12/12 17:22:24
💕
sleep sortの単純な実装。結果はstdoutに出してる。
import Control.Concurrent
sort :: [Int] -> IO ()
sort ns = do
mapM_ (forkIO.single) ns
threadDelay 1000000
single :: Int -> IO ()
single n = threadDelay (n * 1000) >> print n
YoshikuniJujo
12/12 17:35:24
💕
スリープソート
リストを返す版
{-# LANGUAGE BlockArguments #-}
import Control.Concurrent
import Control.Concurrent.STM
import Data.Function
sort :: [Int] -> IO [Int]
sort ns = do
c <- atomically newTChan
mapM_ (forkIO . single c) ns
threadDelay 1000000
atomically $ fix \go -> do
e <- isEmptyTChan c
if e then pure [] else (:) <$> readTChan c <*> go
single :: TChan Int -> Int -> IO ()
single c n = threadDelay (n * 1000) >> atomically (writeTChan c n)
YoshikuniJujo
12/12 17:11:20
💕🤙
カリー化って厳密に言うとHaskellで言うカリー化と他の言語で言うカリー化とは、すこしズレてるように思ったことがある。忘れちゃったけど。
YoshikuniJujo
12/12 17:04:54
💕 🤙 🧡
Haskell Brooks Curryさんは、とりあえず3つの言語に名前を残している。
Haskell
Brook
Curry
さらにカリー化とかカリー=ハワード同型対応などなど、「名前残しすぎ」問題。
YoshikuniJujo
12/12 16:58:51
💕
ちなみにクイックソートが「整列ずみ」の並びでO(n^2)になっちゃうのも「分けながら比較」しているせい。つまひマージソートなら「半分ずつ」に分けるのだけど、「比較の結果」が「分け方」に影響してしまうため、かたよりが生じうるということ。
⬆
YoshikuniJujo
12/12 16:41:20
💕
僕が3大ソートって勝手に呼んでるのが
マージ
クイック
ヒープ
だ。
どれも「分けて」から「組み立てる」というやりかたでO(n log n)を実現してるのだけど、どの時点で「比較と並べ替え」をしているかで見ると面白い。
マージソートは「分ける」ときはそのままで「組み立てのときに比較と並び替え」をしている。
クイックソートは「分けながら比較と並び替え」をしていて「組み立てる」ときにはそのままにしている。
でヒープソートは「分けるときと組み立てるときの両方」で「比較と並び替え」をしている。
YoshikuniJujo
12/12 15:59:04
💕 ⭐️ 🤙 🫧
「Haskellのクイックソート」警察です。
https://zenn.dev/yoshikuni_jujo/articles/sort-algorithms
YoshikuniJujo
12/12 15:35:47
💕
Jamiはpeer-to-peerなのだけど、接続したい相手を指定はどうするのかな。
固定IPが必要とかだとハードルが高い。
その部分だけ中央サーバがあるのかもしれない。
つまり、中央サーバにアカウントとIPアドレスを登録しておいて、接続したい側はそのサーバに問い合わせる感じか。
でIPアドレスがわかればあとはpeer-to-peerで接続できると思う。
YoshikuniJujo
12/12 15:29:02
💕
https://ja.wikipedia.org/wiki/Jami
Jamiはオープンソースでビデオ通話ができるもの。手もとで暗号化が行われるのでプライバシーも保たれる。
⬆
YoshikuniJujo
12/12 15:27:49
💕
あと、マイクの設定をする。
なにかっていうとJamiとやらを試してみたいという話。
PC側で使えるようにして、スマホ側でも使えるようにすれば自分と自分でビデオ通話のテストができる。
⬆
YoshikuniJujo
12/12 15:24:40
💕
Gentoo LinuxからWebカメラを使うのもずいぶん簡単になった。
emerge libv4l
としてから
qvidcap
ってするだけで、とりあえず動作確認ができた。
YoshikuniJujo
12/12 14:56:47
💕
なので、SSDとHDDに階層があってHDDのキャッシュとしてSSDを使うとか、あるいはSSDのswap領域としてHDDを使うみたいな仕組みが欲しくなる。
⬆
YoshikuniJujo
12/12 14:55:26
💕
HaskellでStackを使ってると、カレントディレクトリ化に作られる.stack/下にだだーっていろんなパッケージがビルドされて、しかもバージョンアップごとにたまっていく。で、ビルドされるものなので速度も欲しいし容量も欲しいのでSSDにしてもHDDにしても、どうにも快適ではない。
Stackの仕様がそもそもHDD時代の「水と容量はただ」的考えかたから来てるのだと思う。
YoshikuniJujo
12/12 14:46:07
💕🤙
HDDからSSDへの移行って、人間がはじめて経験する「記憶容量の減少」な気がする。
「古いファイルを消さない」という習慣が身についていたので、ディスク容量がすぐ100%になってしまう。
よく使うファイルをSSDに置き、あまり使わないファイルはHDDに置くみたいな、そういう仕組みが必要。というこすでにあるんじゃないかって気はする。
YoshikuniJujo
12/12 14:39:28
💕
そろそろPC1台組みたいなという気持ちもなくはないのだけど、場所取るんだよなー
小さいのだと選択肢がかなりせばまるし。
一時期はインテルのマザーボードがLinuxのインストールという観点から安心感があったけど、今はどうなのだろうか。
YoshikuniJujo
12/12 12:33:40
💕
レイアウトルール使って書くほうがどっちかというと推奨されてる感じなので。
でも、プログラムでコードを生成する場合など括弧とセミコロンを明示したほうがやりやすいですよね。
Haskellでは括弧とセミコロンを明示すればレイアウトルールのない言語として使うこともできます。
⬆
⬆
YoshikuniJujo
12/12 12:17:59
💕
⬆
⬆
YoshikuniJujo
12/12 11:54:52
💕
これ、実はHaskellを使ってる人のなかでも気付いてない人いると思うのですが、モジュールそのものがdo記法っぽいインデントルールのなかにあるからかもしれません。
module Foo where {
bar;
baz;
}
とも書けると思います。
この書きかたならインデントはとくに意味は持ちません。
インデントルール は{とか;を省略するルールみたいな感じです。
乱文で失礼。わかりにくいところやミスなど聞いていただければ、時間が空いたときに対応しますね。
⬆
YoshikuniJujo
12/12 11:22:49
💕
あと、ライフゲームの盤を定義してるモジュールの例だけど。
盤の一部に特定のパターンがあるかどうかを確認したいみたいな話があったときに、盤の一部を取り出して、それとパターンを比較するみたいな話になるけど、盤、パターン、取り出した部分は、どれもたとえば[[Bool]]で表現できる。
でも、これはあまり筋が良くない。
盤とパターンと取り出した部分はそれぞれモノとしてはちがうので、
newtype Board = Board [[Bool]]
newtype Pattern = Pattern [[Bool]]
newtype Clipped = Clipped [[Bool]]
としたほうが良い。
YoshikuniJujo
12/12 10:25:50
💕🤙
あと「位置」を表すのに(Int, Int)みたいなタプルを使うのは「本当のところ良くな」くて、
data Pos = Pos {
posX :: Int,
poxY :: Int }
みたいにしたほうが良くて、さらにもっと冗長で安全にするなら、
newtype X = X Int
newtype Y = Y Int
data Pos = Pos {
posX :: X,
posY :: Y }
みたいにすれば「もっとベター」な感じはある。
けど、まあ「安全と簡潔」のトレードオフがある。
YoshikuniJujo
12/12 10:22:25
💕🎁 🤙
名前付けるのに「型でわかる情報はいらない」という考え方もある。
clearBoardArea :: Board -> Area -> Board
ではなくて、
clear :: Board -> Area -> Board
としてもいいのではという話。
もちろん名前がかぶる場合にはclearBoardAreaみたいに「区別のため」に冗長にする場合はある。
「説明のため」に冗長にする必要は「より実態にそくしている『型という情報』がある」からいらないという話。
YoshikuniJujo
12/12 10:03:22
💕
おはよーございます🦥🫧
⬆
OrzBruford
12/12 9:58:49
💕:ohayou:
nostr:npub1a7y7u324paehw2zdx8jfl3t72ue0ls4etfalxhg0z2gad738savqhxfdm2 おはよ〜💕
YoshikuniJujo
12/12 10:01:36
💕
モジュールFoo.Barに
data Baz = ...
bazToQux :: Baz -> Qux
quxToBaz :: Qux -> Baz
みたいに定義する代わりにモジュールFoo.Bar.Bazに
data B = ...
toQux :: Baz -> Qux
fromQux :: Qux -> Baz
のようにすることをよくやる。
オブジェクト指向には直観的にわかりやすい名前空間という側面もあるけど、それをなぞっている。
本当はFoo.Bar.Bazという名前の型を用意したいのだけど、できないのでFoo.Bar.Baz.Bとしている。
YoshikuniJujo
12/11 16:55:17
💕
DMはまずRSA暗号で相手を認証して、ディッフィーヘルマンで鍵を交換して、で暗号化して送信するってのが理想だと思う。
そうなると、まずリレーに「アリスがボブにDMを送りたがってるよ」という情報が送られて、それをボブ側のクライアントが発見する。でボブ側のクライアントが認証されて、鍵交換が行われる。でアリスが暗号化したメッセージを送る。そんな感じ。
NIPのDMもそうなってるかな。
非同期風にしたいのであれば、クライアント側でアリスのメッセージを保存しておいて、ボブのクライアントからの応答があった時点で送信するようにすれば、「人間のアリス」にとっては非同期に感じられる、かな。
適当に考えただけなので適当。
YoshikuniJujo
12/11 16:34:03
💕
https://anastasiatetris.com/kokoropyonpyon-kanbun
これわりと好きかも。
「ああ、心がぴょんぴょんするんじゃ」の漢文バージョン。
噫我心如跳躍也
ああ、我(われ)が心(こころ)は躍(おど)り跳(は)ねるが如(ごと)きや。
YoshikuniJujo
12/11 16:20:18
💕
GHCには言語拡張がいろいろあって、ViewPatterns拡張は「変数名いろいろ考えたくない」という人には便利
foo x = bar x'
where x' = baz x
みたいなのを、
foo (baz -> x) = bar x
みたいに書ける。
変数名ってわりと考えるのめんどいので重宝してる。


