fugafuga.write

日々のログ



Haskell

すごいH本 part69

関数型問題解決法 関数型のテクニックを使ってエレガントに 逆ポーランド記法電卓 数式を書く方法として、逆ポーランド記法(reverse polish notation) 略してRPNがある。 RPNでは、演算子は数に挟まれず、数の後ろに書く。 4 + 3 が 4 3 + になる。 4と3を足…

すごいH本 part68

bytestring を使ったファイルコピー ファイルコピー関数を実装する import System.Environment import System.Directory import System.IO import Control.Exception import qualified Data.ByteString.Lazy as B main = do (fileName1:fileName2:_) <- getA…

すごいH本 part67

bytestring まず、遅延評価について wikipedia より 評価しなければならない値が存在するとき、 実際の計算を値が必要になるまで行わないことをいう。 評価法が指示されているが実際の計算が行われていない中間状態の時 それをプロミス(英: promise)や、 …

すごいH本 part66

ランダム性とI/O getStdGen という I/O アクションは、何らかの初期データを使って システムのグローバル乱数ジェネレータを初期化する。 import System.Random main = do gen <- getStdGen putStrLn $ take 20 (randomRs ('a', 'z') gen) 実行 > stack ghc …

すごいH本 part65

もっともっとランダム関数 コインを投げる話の続き。 もっとたくさんのランダム値が欲しい場合どうするか randoms を使う *Main System.Random> :t randoms randoms :: (RandomGen g, Random a) => g -> [a] 乱数ジェネレータを受け取って無限長のランダム値…

すごいH本 part64

ランダム性 ランダム値を扱う。 Haskell は参照透明性を持つので関数が同じ引数で2回呼ばれた場合、 必ず同じ値を返すようになっていなければならない。 その中でランダム値をどのように作るのかを見る。 System.Random モジュールに random という関数があ…

すごいH本 part63

コマンドライン引数 コマンドライン引数をとれるようにする。 import System.Environment import Data.List main = do args <- getArgs progName <- getProgName putStrLn "The arguments are:" mapM putStrLn args putStrLn "The program name is:" putStrL…

すごいH本 part62

Todoリスト Todoリストをテキストファイルに追加するプログラムを書く import System.IO main = do todoItem <- getLine appendFile "todo.txt" (todoItem ++ "\n") ビルドして実行 > stack ghc -- --make appendtodo.hs [1 of 1] Compiling Main ( appendto…

すごいH本 part61

ファイルの読み書き ファイルから読んで端末に表示する baabaa.txt Baa, baa, black sheep, Have you any wool? Yes, sir, yes, syr, Three bags full; 実装 import System.IO main = do handle <- openFile "baabaa.txt" ReadMode contents <- hGetContents…

すごいH本 part60

ファイルとストリーム ファイルの内容を読み込んで大文字にして返すプログラム haiku.txt I'm a cat nyaaan nyaaan nyaaaan nyaaan nyaaaan nyaaaaaaaaaan 実装 import Control.Monad import Data.Char main = forever $ do l <- getLine putStrLn $ map toU…

すごいH本 part59

I/O 関数 putStr main = do putStr "Hey, " putStr "I'm " putStr "Andy!" 実行結果 *Main> main Hey, I'm Andy!*Main> 文字列を引数として受け取る。 受け取った文字列を端末に表示するI/Oアクションを返す。 改行しない。 putChar main = do putChar 't' p…

すごいH本 part58

I/O アクションの中で let 使う let はI/Oアクションの中で普通の値に名前を与えたいときに使う。 import Data.Char main = do putStrLn "Hello, what's your first name?" firstName <- getLine putStrLn "What's your last name?" lastName <- getLine let…

すごいH本 part57

入出力 前回はただのポエムになってしまったので真面目にやっていく。 出力するのに使った関数 putStrLn *Main Lib> :t putStrLn putStrLn :: String -> IO () *Main Lib> :t putStrLn "hello, world" putStrLn "hello, world" :: IO () putStrLn の型は、文…

すごいH本 part56

こんにちは、世界。 〜時を超えて〜 世界との邂逅 HelloWorld.hs main = putStrLn "hello, world" コンパイルして実行ファイルを生成する が、stack を使っているのでH本の通りにやってもできない。 以下のようにするとビルドできた。 > stack ghc -- --make…

すごいH本 part55

型の種類 型とは、値についている何らかの推論をするためについている小さなラベルである。 それと同じように型にも小さなラベルが付いている。 型に付くラベルのことを種類(kind)という。 種類を調べる *Main Lib> :k Int Int :: * * は具体型を表す記号。 …

すごいH本 part54

Map を Functor のインスタンスにする 練習問題とされていたので自分で実装してみる Map,Functorはすでに定義されているので独自のデータ型とFunctorを作る data MyMap k v = MyMap k v deriving (Show) class MyFunctor f where fmap' :: (a -> b) -> f a -…

すごいH本 part53

Tree型 を Functor のインスタンスにする instance Functor Tree where fmap f EmptyTree = EmptyTree fmap f (Node x left right) = Node (f x) (fmap f left) (fmap f right) 実行する *Main> fmap (*2) EmptyTree EmptyTree *Main> fmap (*4) (foldr tree…

すごいH本 part52

Functor 型クラス Functor は全体を写せるものの型クラス class Functor f where fmap :: (a -> b) -> f a -> f b fmap を持つ。デフォルト実装は無い。fは1つの型引数を取る型コンストラクタ。 fmapは、 ある型 a から 別の型 b への関数 ある型 a に適用…

すごいH本 part51

YesNo 型クラスをつくる JavaScript 的なゆるふわ真理値の型クラスをつくる class YesNo a where yesno :: a -> Bool 真理値の概念を何らかの形で含むとみなせる型の値を取り、それが true かどうかを返す。 インスタンスを定義する instance YesNo Int wher…

すごいH本 part50

祝 part 50 型クラスのサブクラス化 Num クラスの型宣言 class (Eq a) => Num a where ... Num 型クラスのインスタンスは Eq 型クラスのインスタンスである必要がある。 サブクラス作成に必要な知識はこれだけ。 多相型を型クラスのインスタンスにする 型コ…

すごいH本 part49

Eq 型クラスの内部 Eq は等値性判定ができる値の型クラス。== と /= という関数を定義している。 標準ライブラリにおける Eq 型クラスの定義 class Eq a where (==) :: a -> a -> Bool (/=) :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) …

すごいH本 part48

二分探索木を実装する 1つの要素が2つの子要素へのポインタを持つ 左の子は親より小さい 右の子は親より大きい それぞれの子要素は 0 or 1 or 2 個の要素を持つ 二分探索木はある要素の左側はその要素より小さく、 右側はその要素より大きいということが保証…

すごいH本 part47

再帰的なデータ構造 データ型の定義時に再帰構造を作ることができる 例としてオリジナルのリスト型を作りながら見ていく *Main> [5] [5] *Main> 5 : [] [5] *Main> [4,5,6,7] [4,5,6,7] *Main> 4 : 5 : 6 : 7 : [] リストデータ型のデータ構造としては、 空…

すごいH本 part46

型シノニムの多相化 型シノニムに型引数をとることができる type AssocList k v = [(k, v)] 型引数を部分適用すると新しい型コンストラクタが作れる type IntMap v = Map Int v こうも書ける type IntMap = Map Int Data.Map を修飾付インポートをする時は型…

すごいH本 part45

型シノニムの話 [Charl] と String は同値でこれは型シノニムを使って実装されている。型シノニムはある方に別の名前を与えて、コードやドキュメントを読みやすくする。 このように書く type String = [Char] この型宣言と toUpperString :: [Char] -> [Char…

Haskell で Fizzbuzz

Haskell の練習のため、Fizzbuzzを書いた。最初本当に何も書けなくてびっくりした。 fizzbuzz :: Int -> [String] fizzbuzz 0 = [] fizzbuzz x | x `mod` 15 == 0 = fizzbuzz (x-1) ++ ["FizzBuzz"] | x `mod` 3 == 0 = fizzbuzz (x-1) ++ ["Fizz"] | x `mod…

すごいH本 part44

Ord 型クラスの話 順序付け可能な型のための型クラス Ord の話。 同じ型の値を2つ比較したとき、その2つが異なる値コンストラクタから生成されているなら先に定義されているほうが小さいとみなされる。 *Main> True > False True *Main> True < False False …

すごいH本 part43

Show と Read は文字列へ変換できるもの、文字列から変換できるものの型クラス。ある型をそれらのインスタンスにしたいなら、その型の値コンストラクタにフィールドがあれば、それらの型も Show や Read に属している必要がある。 data Person = Person { fi…

すごいH本 part42

インスタンスの自動導出 型クラスはある振る舞いを定義するインターフェースである Haskell ではまずデータ型をつくり、それがどう振る舞えるかを考える 仮にその型が等値制をテストできるなら Eq型クラスのインスタンスにする 仮にその型が大小比較できるも…

すごいH本 part41

三次元ベクトルの型とベクトルの演算を作る data Vector a = Vector a a a deriving (Show) vplus :: (Num a) => Vector a -> Vector a -> Vector a (Vector i j k) `vplus` (Vector l m n) = Vector (i+l) (j+m) (k+n) dotProd :: (Num a) => Vector a -> V…