エレファント・ビジュアライザー調査記録

ビジュアルプログラミングで数式の変形を表すことを考えていくブロクです。

関数型言語の拡張(2)

プログラミング言語に関する質問をChatGPTに入力してみることの続きです。変数を変更することができる関数型言語のプログラムを変数を変更することができない関数型言語のプログラムに変換するという問題を考えます。ここで扱う例はクロージャーには関係なくなるかもしれないので、「関数型言語の拡張」は「関数プログラミングクロージャー」に引き継いだのですけど、復活しました。クロージャーに関連しないことはこちらに書くことにしました。

有限の回数で終了するプログラムであれば、変数を変更することができない関数型言語のプログラムに変換することはできると思われるので、有限の回数では終了しないプログラムを考えます。また、1、2、3…のように規則的な列を返すものは、変数を変更することができない関数型言語のジェネレーターで書くことができると思われるので、無限個のデータを必要とするプログラムを考えます。次のような例を考えます。

次のようなプログラムを考えます。今日から一日に一回、気象観測システムからその日の天気が晴れなのか雨なのかという情報が送られてきます。この情報をある日受け取るとこのプログラムは、今日からその日までに受け取ったすべての情報に基づいて、次の日の天気が雨である確率を予測し、それを返します。このようなプログラムを C# で書いてください
このプログラムを Haskell で書き直してください

以下は、Haskellで提供されたプログラムです。Haskell関数型言語であり、パターンマッチングや高階関数を活用してコードを記述します。

module Main where

type WeatherData = [Bool]

-- 今日の天気情報を追加する関数
addWeatherData :: WeatherData -> Bool -> WeatherData
addWeatherData weatherData isRainy = weatherData ++ [isRainy]

-- 次の日の天気が雨である確率を予測する関数
predictNextDayRainProbability :: WeatherData -> Double
predictNextDayRainProbability weatherData
    | null weatherData = error "No weather data available."
    | otherwise = fromIntegral (length (filter id weatherData)) / fromIntegral (length weatherData)

main :: IO ()
main = do
    let weatherData = [True, False, True] -- 例: 雨、晴れ、雨
    let rainProbability = predictNextDayRainProbability weatherData
    putStrLn $ "Predicted probability of rain for the next day: " ++ show (rainProbability * 100) ++ "%"

このHaskellプログラムは、指定された天気データを元に、次の日の雨の予測確率を計算します。`addWeatherData`関数は、天気データリストに新しい天気情報を追加します。`predictNextDayRainProbability`関数は、与えられた天気データから雨の確率を計算します。`main`関数では、例の天気データを使用して予測を行い、結果を出力します。

これはデータが有限個ですね。

無限個のデータを扱えるように書き直してください

Haskellでは、無限のデータを扱うことが可能です。無限のデータストリームを表すために、遅延評価とリストを使用します。以下は、無限のデータを扱うように書き直したHaskellのプログラムです。

module Main where

type WeatherData = [Bool]

-- 今日の天気情報を追加する関数
addWeatherData :: WeatherData -> Bool -> WeatherData
addWeatherData weatherData isRainy = weatherData ++ [isRainy]

-- 次の日の天気が雨である確率を予測する関数
predictNextDayRainProbability :: WeatherData -> Double
predictNextDayRainProbability weatherData
    | null weatherData = error "No weather data available."
    | otherwise = fromIntegral (length (filter id weatherData)) / fromIntegral (length weatherData)

main :: IO ()
main = do
    let weatherData = cycle [True, False] -- 雨、晴れの無限のデータ
    let rainProbability = predictNextDayRainProbability (take 1000 weatherData) -- 最初の1000個のデータを使用して予測
    putStrLn $ "Predicted probability of rain for the next day: " ++ show (rainProbability * 100) ++ "%"

このプログラムでは、`cycle`関数を使用して `[True, False]` のリストを無限に繰り返し、無限の天気データを生成しています。そして、最初の1000個のデータを使用して次の日の雨の予測確率を計算します。

これはデータを受け取っていないので違います。