Haskellは何言語か。またその特徴を書け。
関数型言語・宣言型言語
第一級関数(必須)
参照透過性
高階関数
遅延評価
多くのプログラミング言語は文法や機能の挙動を確かめるために、REPLと呼ばれる対話環境が 用意されることがある。Haskellでは何というコマンドを使うか。また、REPLは何の略か。
ghci
Read Eval Print Loop
下記のコードで得られる結果を書け。また下記のようなリストを何と言い、Haskellの何という特徴により正常に動作するか書け。
def from(n: Int): Stream[Int] = Stream.cons(n, from(n + 13))
from(13).take(5).toList
> res: List[Int] = List(13, 26, 39, 52, 65)
無限リスト
遅延評価
リスト [1,2,3,4,5] を返すコードを2種類の方法で定義せよ。ただし、(++)関数、自作の関数、リスト内包記法を使ってはならない。
(1 to 5).toList
1 :: 2 :: 3 :: 4 :: 5 :: Nil
リストとペアの違いを書き、2番目の要素を取り出すようなコードを、それぞれについて書け。
List(1, 2, 3)(1)
List(1, 2, 3).apply(1)
(1,2)._2
// もしくは
val (_, snd) = (1,2)
val (_ :: snd :: _) = List(1, 2, 3, 4)
関数 head の型定義は次のようになっている、head :: [a] -> a 型定義中のa, b などの変数を何と言うか書け。 またこのような変数を利用している関数のことは何と呼ばれるか。 さらに、この変数と型の文字列の違いは何で判断するか書け。
型変数
多相関数
型は大文字から始まる
以下のコードの型を書け。ただし、出来うる限り汎用的な型にせよ。
// haskellのように出来うる限り汎用的にするにはNumericというtraitを使う必要があるが、
// かなり難解なコードになる
def sum(list: List[Int]): Int =
list match {
case Nil => 0
case x :: xs => x + sum(xs)
}
型クラス | 制約 | 関数定義 |
---|---|---|
Eq | 等価性 | ==, /= |
Ord | 順序 | <, > <=, >= |
Show | 文字列表現 | show |
Read | リテラル表記 | read |
Enum | 列挙 | succ, pred |
Bounded | 上限・下限 | maxBound, minBound |
任意の階乗を求める関数factorialを再帰とパターンマッチを利用して定義せよ。型定義も書くこととする。
def factorial(x: Int): Int =
if(x == 1) 1
else x * factorial(x - 1)
max'を定義せよ。型定義も書くこととする。
max' :: (Ord a) => a -> a -> a
max' x y = if x >= y then x else y
任意のリストから最大値を見つけるmaximum'を定義せよ。
maximum' :: (Ord a) => [a] -> a
maximum' xs = foldl1 max xs
Intと任意の値を取り、受け取ったIntの数だけ任意の値を複製するreplicate'関数を定義せよ。
replicate' :: Int -> a -> [a]
replicate' 0 _ = []
replicate' n x = x : replicate (n - 1) x
zipWith'を定義せよ。
zipWith' :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith' _ [] _ = []
zipWith' _ _ [] = []
zipWith' f (x:xs) (y:ys) = f x y : zipWith' f xs ys
1~100までのリストから奇数のみを取り出し、その後全ての要素を二乗する関数evenDoubleを、 リスト内包記法、高階関数の3パターンを使って定義せよ。
[x ^ 2 | x <- [1..100], x `mod` 2 == 0]
filter (\x -> x `mod` 2 == 0) . map (^2) $ [1..100]
map'を再帰・高階関数を使った2種類の方法で定義せよ。
map' :: (a -> b) -> [a] -> [b]
map' f [] = []
map' f (x:xs) = f x : map' f xs
map' :: (a -> b) -> [a] -> [b]
map' f xs = foldr (\x acc -> f x : acc) [] xs
filter'を定義せよ。
filter' :: (a -> Bool) -> [a] -> [a]
filter' p xs = foldr (\x acc -> if p x then x : acc else acc) [] xs
関数を引数に取り、最初の2つの引数が入れ替わった関数を返すflip'をwhere、カリー化、ラムダ式を使った3パターン定義せよ。
flip' :: (a -> b -> c) -> b -> a -> c
flip' f = g
where g y x = f x y
flip' :: (a -> b -> c) -> b -> a -> c
flip' f y x = f x y
flip' :: (a -> b -> c) -> b -> a -> c
flip' f = \x y -> f y x
foldlを使いリストの合計を算出するsum'を定義せよ。
sum' :: (Num a) => [a] -> a
sum' = foldl1 (+)
reverse'を再帰・畳込みを使った2種類の定義せよ。
reverse' :: [a] -> [a]
reverse' [] = []
reverse' (x:xs) = reverse' xs ++ [x]
reverse' :: [a] -> [a]
reverse' xs = foldl (flip (:)) [] xs
以下の式を関数合成と関数適用演算子を利用して、書き換えろ。
sum (replicate 5 (max 6.7 8.9))
sum . replicate 5 $ max 6.7 8.9