親関数でインスタンス化される構造体があり、そのインスタンス化されたデータを、その親関数からの関数の呼び出しで変更したいと思います。不自然な例を次に示します。
import Data.List
data MyLists = MyLists {
myInts :: [Int],
myBools :: [Bool]
} deriving (Show)
addIntToList :: Int -> MyLists -> MyLists
addIntToList x main_lists =
main_lists { myInts = Data.List.insert x my_ints }
-- might make a call to another child function that modifies main_list here, and so on (i.e., this is the vertical problem I see with this structuring)
where
my_ints = myInts main_lists
main :: IO()
main = do
let my_main_lists = MyLists [1,2,3] [False, True, False]
let my_new_main_lists = addIntToList 4 my_main_lists
print my_new_main_lists
let my_new_new_main_lists = addBoolToList True my_new_main_lists
print my_new_new_main_lists
-- and so on (this is the lateral problem I see with this code structuring)
このコードを構造化する、またはこれと同様のタスクを実行するための代替方法は何ですか?もっと簡潔な方法はありますか?
子関数への関数呼び出しの長いチェーンを作成すると、これは特に臭い(つまり、コードの臭い)になることを付け加えておきます。それらはすべて、新しいものを返す必要があるか、何もせずにMyLists
単に戻る必要があります。main_list
それと、親も処理しなければならない可能性がありMyList
、別の戻り値(たとえば-> (Bool, MyList)
)。
したがって、すべてMyListパラメーターと戻り値を必要とする関数呼び出しのツリー構造を想像することができます。それは最適ではないようです。
これが私が話しているようなもののより具体的な例です。https://github.com/mokehehe/monao(haskellのスーパーマリオクローン)でコードを参照します。state.monadが使用されることはなく、コード全体に流れる必要のある上位レベルの構造体があることがわかります(たとえば、Main.hsのGameGame)。