P74 - 不用 do 记法编写 IO

2026-09-07 00:00    #Haskell   #99题   #Monad  

P74 - 不用 do 记法编写 IO

IO monad without do notation

官方模块:Problems.P74 核心函数:askGoldbach


← P73 S 表达式 | P75 Maybe Monad →


题目描述

从输入句柄读取一个偶数,调用 P40 分解,再把 n=a+b 写到输出句柄。要求不用 do,直接使用 (>>=)(>>)

实现

方法一:»= 绑定风格

 1import System.IO (Handle, hGetLine, hPutStr, hPutStrLn)
 2
 3askGoldbach :: Handle -> Handle -> IO ()
 4askGoldbach input output =
 5  hGetLine input >>= \text ->
 6    let n = read text :: Integer
 7        (a,b) = goldbach n
 8    in hPutStr output (show n ++ "=")
 9       >> hPutStr output (show a ++ "+")
10       >> hPutStrLn output (show b)

(>>=) 把读取到的字符串交给后续函数;(>>) 只关心动作顺序,忽略前一个动作的 () 结果。

方法二:纯格式化后一次输出

1askGoldbach :: Handle -> Handle -> IO ()
2askGoldbach input output =
3  hGetLine input >>=
4    hPutStrLn output . format . (read :: String -> Integer)
5
6format :: Integer -> String
7format n = show n ++ "=" ++ show a ++ "+" ++ show b
8  where
9    (a, b) = goldbach n

这个版本把哥德巴赫分解和字符串拼接留在纯函数 format 中,IO 部分只做一次读取和一次写入。两种方法都遵守“不使用 do”的限制。

方法对比

方法IO 动作组织
多次顺序写入(>>) 串联三个输出动作
一次格式化输出纯函数生成整行,只执行一次写入

测试

使用内容为 104 的输入句柄时,输出为:

1104=3+101

return 在这里不是命令式语言的“返回语句”,而是把普通值放入某个 Monad 的函数。

参考


← P73 S 表达式 | P75 Maybe Monad →