【Haskell】基本文法【言語習得への道】
コメント
プログラミングでは、コード中にコメントを書くことができます。
Haskellでは文頭に「--」を書くことで、コメントとして扱われます。
コメント扱いされた文は実行されることはありません。
-- この行はコメントです.
-- putStrLn "コメントです"
main :: IO ()
main = do
putStrLn "Hello, World"
putStrLn "Not, Comment"
-- 実行結果
-- Hello, World
-- Not, Comment
変数
Haskellで変数をつける時は、左に変数名・右に数値や文字列を置き、間に「=」を挟みます。変数と関数は名前を小文字で始める必要があります。 大文字で始めるとエラーになります。
また,Haskellの変数では、値を代入は基本は一度しかできないと思う。(たぶん間違っている)
型宣言と代入を同時
-- データ型と初期値を同時
String text = "text"
String text2 = "Text"
main :: IO ()
main = do
-- 出力
putStrLn text
putStrLn text2
-- エラー出た
-- text2 = "TEXT"
-- putStrLn text2
-- 実行結果
-- text
-- Text
型宣言と代入が別
-- データ型→初期値
text :: String
text = "text"
text2 :: String
text2 = "Text"
main :: IO ()
main = do
-- 出力
putStrLn text
putStrLn text2
-- エラー出た
-- text2 = "TEXT"
-- putStrLn text2
-- 実行結果
-- text
-- Text
局所的な変数や関数
let式は、局所的な変数や関数を定義するために使われます。let式はinキーワードと組み合わせて使われ、定義された変数や関数はinの後の式で使用できます。
-- let式の例
calculateArea :: Float -> Float
calculateArea radius =
let area = pi * square radius
square x = x * x
in area
main :: IO ()
main = do
let radius = 5.0
print (calculateArea radius)
また、doブロック内でもletを使って変数を定義できます。この場合、inは不要です。
-- let式の例
main :: IO ()
main = do
let radius = 5.0
square x = x * x
print (pi * square radius)
where句は、関数定義の後に局所的な変数や関数を定義するために使われます。where句で定義された変数や関数は、その関数全体で使用できます。
-- where句の例
calculateArea :: Float -> Float
calculateArea radius = area
where
area = pi * square radius
square x = x * x
main :: IO ()
main = do
let radius = 5.0
print (calculateArea radius)
letとwhereの使いどこ
sphere r =
let pi = 3.1415
in
4/3 * pi * r * r * r
main = do
print(sphere(10))
-- 4188.666666666666
sphere r = 4/3 * pi * r * r * r
where
pi = 3.1415
main = do
print(sphere(10))
-- 4188.666666666666
長い変数名
変数名が長い時に、_か大文字で区切ります。
-- _で繋ぐ
text_text :: String
text_text = "text"
-- -で繋ぐ
-- エラー
-- text-Text :: String
-- text-Text = "Text"
-- 小文字→大文字で繋ぐ
textText :: String
textText = "Text"
-- 大文字で繋ぐ
textTextUpper :: String
textTextUpper = "TEXT"
-- 出力
main :: IO ()
main = do
putStrLn text_text
-- putStrLn text-Text
putStrLn textText
putStrLn textTextUpper
-- 実行結果
-- text
-- Text
-- TEXT
関数
string00 :: IO ()
string00 = do
let text = "text"
let _text = "Text"
putStrLn text
putStrLn _text
let helloworldmessage = "Hello, World"
let hello_world_message = "Hello, World"
putStrLn helloworldmessage
putStrLn hello_world_message
main :: IO ()
main = string00
-- 実行結果
-- text
-- Text
-- Hello, World
-- Hello, World
型宣言
string00 :: IO ()
string00関数の型を宣言しています。
IO ()は、この関数がIOアクションであり、副作用を持つことを示しています。返り値の型は()(ユニット型)です。
関数本体
string00 = do
let text = "text"
let _text = "Text"
putStrLn text
putStrLn _text
let helloworldmessage = "Hello, World"
let hello_world_message = "Hello, World"
putStrLn helloworldmessage
putStrLn hello_world_message
doブロック内で一連のIOアクションを定義しています。
letを使って変数を定義します。Haskellでは変数は不変(イミュータブル)です。
putStrLnは文字列をコンソールに出力するIOアクションです。
メイン関数
main :: IO ()
main = string00
main関数もIOアクションであり、プログラムのエントリーポイントです。
main関数内でstring00を呼び出しています。
文字列
基本文法
-- 初期設定
import System.IO
-- 文字列
helloWorld :: String -> String
helloWorld str1 = "Hello World"
-- 実行
main :: IO ()
main = do
let echoStr = helloWorld "mass"
putStrLn echoStr
-- Hello World
-- 文字列連結
let helloWorld2 str1 = "Hello World" ++ str1
let echoStr2 = helloWorld2 "mass"
putStrLn echoStr2
-- Hello Worldmass
-- 改行
let helloWorld3 str1 = "Hello World\n" ++ str1
let echoStr3 = helloWorld3 "mass"
putStrLn echoStr3
-- Hello World
-- mass
コードの解説
このHaskellコードは、NimのコードをHaskellに変換したものです。それぞれの関数と実行部分について説明します。
-- 初期設定
import System.IO
`System.IO`モジュールをインポートしています。これは標準入力や標準出力を扱うために必要です。
-- 文字列
helloWorld :: String -> String
helloWorld str1 = "Hello World"
`helloWorld`関数は、引数として文字列を受け取り、常に "Hello World" を返します。Nimの `HelloWorld` 関数に相当します。
-- 実行
main :: IO ()
main = do
let echoStr = helloWorld "mass"
putStrLn echoStr
-- Hello World
`main`関数はHaskellプログラムのエントリーポイントです。`helloWorld`関数を呼び出し、その結果を `echoStr` に代入し、`putStrLn`で標準出力に出力します。
-- 文字列連結
let helloWorld2 str1 = "Hello World" ++ str1
let echoStr2 = helloWorld2 "mass"
putStrLn echoStr2
-- Hello Worldmass
`helloWorld2`関数は、引数として受け取った文字列を "Hello World" に連結して返します。Nimの `HelloWorld2` 関数に相当します。`++`はHaskellの文字列連結演算子です。
-- 改行
let helloWorld3 str1 = "Hello World\n" ++ str1
let echoStr3 = helloWorld3 "mass"
putStrLn echoStr3
-- Hello World
-- mass
`helloWorld3`関数は、引数として受け取った文字列を "Hello World\n" に連結して返します。Nimの `HelloWorld3` 関数に相当します。`\n`は改行文字です。
全体として、`main`関数内で3つの異なる関数を呼び出し、それぞれの結果を標準出力に出力しています。
整数を文字列に変換
import Text.Printf (printf)
main :: IO ()
main = do
let i = 5 :: Int
let a = show i -- 文字列へ変換
putStrLn $ "5以下:" ++ a -- 文字列の結合
putStrLn $ "5以下:" ++ show i
printf "5以下:%d" i
解説
import Text.Printf (printf)
`printf`関数をインポートしています。`printf`はC言語の`printf`と同様にフォーマットされた文字列を出力するために使用されます。
main :: IO ()
main = do:
`main`関数の型を定義しています。`main`はHaskellプログラムのエントリーポイントで、`IO`アクションを返します。
`do`ブロックを使って複数のIOアクションを順に実行します。
let i = 5 :: Int
変数`i`を定義し、整数`5`を代入しています。`:: Int`は型注釈で、`i`が`Int`型であることを明示しています。
let a = show i
変数`a`を定義し、`i`を文字列に変換して代入しています。`show`関数は任意の型を文字列に変換します。
putStrLn $ "5以下:" ++ a
`putStrLn`関数を使って、文字列を標準出力に出力します。`"5以下:" ++ a`は文字列の結合を行っています。
putStrLn $ "5以下:" ++ show i
同様に、`i`を`show`関数で文字列に変換し、結合して出力しています。
printf "5以下:%d" i
`printf`関数を使って、フォーマットされた文字列を出力します。`%d`は整数をフォーマットするためのプレースホルダで、`i`の値がここに挿入されます。
このコードは、整数`5`を文字列に変換して結合し、異なる方法で出力する例を示しています。
数値
基本的な算術演算と文字列の出力を行います
main :: IO ()
main = do
print 42
print (42 + 21) -- 足し算
print (42 - 21) -- 引き算
print (42 * 2) -- かけ算
print (42 / 21) -- 割り算
putStrLn "42 + 21" -- 文字列
-- 実行結果
-- 42
-- 63
-- 21
-- 84
-- 2.0
-- 42 + 21
main関数の定義
main :: IO ()
`main`関数はHaskellプログラムのエントリーポイントです。`IO ()`はこの関数が入出力操作を行い、副作用を持つことを示しています。
入出力操作の開始
main = do
`do`ブロックを使って、複数の入出力操作を順番に実行します。
数値の出力
print 42
`print`関数を使って、数値`42`を標準出力に表示します。
足し算の結果を出力
print (42 + 21) -- 足し算
`42 + 21`の計算結果を`print`関数で表示します。
引き算の結果を出力
print (42 - 21) -- 引き算
`42 - 21`の計算結果を`print`関数で表示します。
かけ算の結果を出力
print (42 * 2) -- かけ算
`42 * 2`の計算結果を`print`関数で表示します。
割り算の結果を出力
print (42 / 21) -- 割り算
`42 / 21`の計算結果を`print`関数で表示します。
文字列の出力
putStrLn "42 + 21" -- 文字列
`putStrLn`関数を使って、文字列`"42 + 21"`を標準出力に表示します。
リスト型
配列の操作を行います。
import Data.List (intercalate)
main :: IO ()
main = do
let ary = ["a", "b", "c", "d", "e", "f"]
putStrLn $ show ary ++ ", " ++ show (length ary)
putStrLn $ ary !! 0
putStrLn $ ary !! 5
putStrLn $ ary !! (length ary - 1)
let results = [ary !! 0, ary !! 2]
putStrLn $ show results
-- ["a","b","c","d","e","f"], 6
-- a
-- f
-- f
-- ["a","c"]
モジュールのインポート
import Data.List (intercalate)
`intercalate`関数を使用するために`Data.List`モジュールをインポートしています。
main関数の定義
main :: IO ()
main = do
`main`関数はHaskellプログラムのエントリーポイントです。`IO ()`はこの関数が入出力操作を行い、副作用を持つことを示しています。
配列の初期化
let ary = ["a", "b", "c", "d", "e", "f"]
`let`を使って、文字列のリスト`ary`を初期化します。
配列とその長さを出力
putStrLn $ show ary ++ ", " ++ show (length ary)
`putStrLn`関数を使って、`ary`リストとその長さを表示します。`show`関数はリストを文字列に変換します。
配列の特定の要素を出力
putStrLn $ ary !! 0
putStrLn $ ary !! 5
putStrLn $ ary !! (length ary - 1)
`putStrLn`関数を使って、`ary`リストの特定の要素を表示します。`!!`演算子はリストの指定されたインデックスの要素を取得します。
新しい配列 results を作成し、特定の要素をコピー
let results = [ary !! 0, ary !! 2]
`let`を使って、`ary`リストの特定の要素をコピーして新しいリスト`results`を作成します。
results 配列を出力
putStrLn $ show results
`putStrLn`関数を使って、`results`リストを表示します。`show`関数はリストを文字列に変換します。
ループ文
数値と配列を使ったループの例を示しています。
main :: IO ()
main = do
-- 数字のfor文
putStrLn "数字のループ文"
mapM_ print [0..6]
let ary = ["a", "b", "c", "d", "e", "f"]
putStrLn $ "リスト: " ++ show ary
putStrLn $ "リストのループ文: " ++ show (length ary)
putStrLn "リストのループ文"
mapM_ putStrLn ary
-- 数字のループ文
-- 0
-- 1
-- 2
-- 3
-- 4
-- 5
-- 6
-- リスト: ["a","b","c","d","e","f"]
-- リストのループ文: 6
-- リストのループ文
-- a
-- b
-- c
-- d
-- e
-- f
main関数の定義
main :: IO ()
main = do
`main`関数はHaskellプログラムのエントリーポイントです。`IO ()`はこの関数が入出力操作を行い、副作用を持つことを示しています。
数字のループ文
putStrLn "数字のfor文"
mapM_ print [0..6]
`putStrLn`関数を使って、"数字のループ文"という文字列を表示します。`mapM_`関数を使って、0から6までの数字を順に`print`関数で表示します。
配列の初期化
let ary = ["a", "b", "c", "d", "e", "f"]
`let`を使って、文字列のリスト`ary`を初期化します。
リストの出力
putStrLn $ "リスト: " ++ show ary
putStrLn $ "リストのループ文: " ++ show (length ary)
`putStrLn`関数を使って、`ary`リストとその長さを表示します。`show`関数はリストを文字列に変換します。
リストのfor文
putStrLn "リストのループ文"
mapM_ putStrLn ary
`putStrLn`関数を使って、"リストのループ文"という文字列を表示します。`mapM_`関数を使って、`ary`リストの各要素を順に`putStrLn`関数で表示します。
条件文
以下のコードは、0から10までの数値をループし、それぞれの数値が5以下かどうかを判定して出力するものです。
import Control.Monad (when)
main :: IO ()
main = do
-- 0から10までの範囲でループを実行
mapM_ (\i -> when (i <= 5) $ do
print (i <= 5) -- 条件が真であることを表示
putStrLn $ "5以下:" ++ show i) [0..10]
-- 0から10までの範囲で再度ループを実行
mapM_ (\i -> when (not (i <= 5)) $ do
print (i <= 5) -- 条件が偽であることを表示
putStrLn $ "5以上:" ++ show i) [0..10]
-- True
-- 5以下:0
-- True
-- 5以下:1
-- True
-- 5以下:2
-- True
-- 5以下:3
-- True
-- 5以下:4
-- True
-- 5以下:5
-- False
-- 5以上:6
-- False
-- 5以上:7
-- False
-- 5以上:8
-- False
-- 5以上:9
-- False
-- 5以上:10
モジュールのインポート
import Control.Monad (when)
`when`関数を使用するために`Control.Monad`モジュールをインポートしています。
main関数の定義
main :: IO ()
main = do
`main`関数はHaskellプログラムのエントリーポイントです。`IO ()`はこの関数が入出力操作を行い、副作用を持つことを示しています。
0から10までの範囲でループを実行
mapM_ (\i -> when (i <= 5) $ do
print (i <= 5) -- 条件が真であることを表示
putStrLn $ "5以下:" ++ show i) [0..10]
`mapM_`関数を使って、0から10までの範囲でループを実行します。`when`関数を使って、`i`が5以下の場合に条件が真であることを表示し、"5以下:"と`i`の値を表示します。
0から10までの範囲で再度ループを実行
mapM_ (\i -> when (not (i <= 5)) $ do
print (i <= 5) -- 条件が偽であることを表示
putStrLn $ "5以上:" ++ show i) [0..10]
`mapM_`関数を使って、0から10までの範囲で再度ループを実行します。`when`関数を使って、`i`が5以下でない場合に条件が偽であることを表示し、"5以上:"と`i`の値を表示します。