見出し画像

Haskellでキューを実装しよう!

キューは、FIFO(First In, First Out)方式でデータを管理するデータ構造です。プログラミングにおいて、キューは非常に基本的なデータ構造であり、タスクのスケジューリングやリソース管理などでよく使われます。この記事では、Haskellを使ってキューをゼロから実装し、その使い方や応用例を紹介します。

1. キューの基本操作

キューには次の基本操作があります

  1. enqueue: 要素を追加する。

  2. dequeue: 最初に追加した要素を取り出す。

  3. isEmpty: キューが空かどうかを確認する。

2. キューの実装

Haskellでリストを使い、キューを簡単に作ることができます。Queue.hsというファイルにプログラムを書きましょう。

この実装では、2つのリストを使用してキューを表現しています。frontリストは取り出し用、backリストは追加用として機能します。要素を取り出す際、frontリストが空であれば、backリストを反転してfrontリストとし、効率的な操作を実現しています。

module Queue (
    Queue,
    empty,
    enqueue,
    dequeue,
    isEmpty
) where

-- キューのデータ型定義
data Queue a = Queue [a] [a]
    deriving (Show)

-- 空のキューを作成
empty :: Queue a
empty = Queue [] []

-- 要素を追加
enqueue :: a -> Queue a -> Queue a
enqueue x (Queue front back) = Queue front (x : back)

-- 要素を取り出す
dequeue :: Queue a -> Maybe (a, Queue a)
dequeue (Queue [] []) = Nothing
dequeue (Queue [] back) = dequeue (Queue (reverse back) [])
dequeue (Queue (x:xs) back) = Just (x, Queue xs back)

-- キューが空かどうかを確認
isEmpty :: Queue a -> Bool
isEmpty (Queue [] []) = True
isEmpty _             = False

3. キューの使い方

キューを使って、複数のタスクを順番に処理するプログラムを書いてみましょう。Main.hsというファイルにプログラムを保存します。

import Queue

-- タスクを処理する関数
processTasks :: [String] -> IO ()
processTasks tasks = process (foldl (flip enqueue) empty tasks)
  where
    process q
      | isEmpty q = return ()
      | otherwise = case dequeue q of
          Just (task, q') -> do
            putStrLn $ "Processing task: " ++ task
            -- ここでタスクの処理を行う
            process q'
          Nothing -> return ()

main :: IO ()
main = do
    let tasks = ["Task 1", "Task 2", "Task 3"]
    processTasks tasks

4. 実行する

Haskellの環境構築は、こちらを確認してください。

下記のコマンドで、プログラムを実行します

runhaskell Main.hs

以下のように表示されれば成功です

Processing task: Task 1
Processing task: Task 2
Processing task: Task 3

まとめ

キューはシンプルですが、タスクのスケジューリングやリソース管理など多くの場面で使われます。Haskellを使えば、簡単に実装して応用できます。ぜひ試してみてください!

いいなと思ったら応援しよう!