Namaran

Code daily. Without assist.

2026-09-19

LookupChain.hs

lookupChain :: [(String, String)] -> [(String, Int)] -> String -> Maybe Int
lookupChain step1 step2 key = lookup key step1 >>= \mid_ -> lookup mid_ step2

main :: IO ()
main = do
  let names = [("alice", "id1"), ("bob", "id2")]
      scores = [("id1", 90), ("id3", 70)]
  print (lookupChain names scores "alice")
  print (lookupChain names scores "bob")
  print (lookupChain names scores "carol")

lookupChainは、途中で見つからなかった場合に-1のような番兵値を返す代わりにMaybe Intを使っています。mainは何を出力するでしょうか?(3行)

Answer

Just 90NothingNothing — 1行ずつ。"alice"names"id1"に見つかり、続けてscores"id1"を引くとJust 90になります。"bob"namesでは"id2"に見つかりますが、scoresには"id2"が無いので2段目のlookupNothingを返します。"carol"namesの時点で見つからずNothingになり、Maybe>>=は左側がNothingだと右側の関数を一切呼ばずにNothingを返す(短絡する)ので、2段目のlookupは実行されません。もしIntだけで書いて「見つからなければ-1」という番兵値にしていたら、各段で-1かどうかを自分で確認しなければならず、確認を1箇所でも忘れると見つからなかったはずの値が次の段にそのまま渡ってしまいます。Maybeという専用の型を使うことで、「まだ値がない」状態が型として表現され、>>=がその伝播を代わりに面倒みてくれます。