【发布时间】:2020-10-06 01:10:52
【问题描述】:
我想编写一个函数来读取没有do 符号的Int。它可以工作(见下文),但我想知道 readMaybe 周围的位是否可以以无点形式编写(或以其他方式清理一下)?
main :: IO ()
main = getLine >>= (\x -> return $ (readMaybe x :: Maybe Int)) >>= print
【问题讨论】:
我想编写一个函数来读取没有do 符号的Int。它可以工作(见下文),但我想知道 readMaybe 周围的位是否可以以无点形式编写(或以其他方式清理一下)?
main :: IO ()
main = getLine >>= (\x -> return $ (readMaybe x :: Maybe Int)) >>= print
【问题讨论】:
第 1 步:将 lambda 替换为其无点等效项:
main :: IO ()
main = getLine >>= return . (readMaybe :: String -> Maybe Int) >>= print
第 2 步:将 m >>= return . f 替换为 f <$> m:
main :: IO ()
main = (readMaybe :: String -> Maybe Int) <$> getLine >>= print
第 3 步:将 f <$> m >>= g 替换为 m >>= g . f:
main :: IO ()
main = getLine >>= print . (readMaybe :: String -> Maybe Int)
第 4 步:使用类型应用程序,而不是写出冗长、笨拙的类型:
{-# LANGUAGE TypeApplications #-}
main :: IO ()
main = getLine >>= print . readMaybe @Int
作为在第 2 步和第 3 步中使用 <$> 的替代方法,您可以仅使用 monad 法则来完成相同的操作,如下所示(在第 1 步之后继续):
将m >>= f >>= g 替换为m >>= \x -> f x >>= g(关联性):
main :: IO ()
main = getLine >>= \x -> (return . (readMaybe :: String -> Maybe Int)) x >>= print
简化.远:
main :: IO ()
main = getLine >>= \x -> return ((readMaybe :: String -> Maybe Int) x) >>= print
将return x >>= f 替换为f x(左身份):
main :: IO ()
main = getLine >>= \x -> print ((readMaybe :: String -> Maybe Int) x)
现在只需将新的 lambda 替换为它的无点等效项,您最终会回到与第 3 步完全相同的位置。
【讨论】:
get input >>= parse >>= something >>= something >>= print 形式的结构,有什么想法可以在这种情况下简化(\x -> return $ (readMaybe x :: Maybe Int))?
getLine >>= return . readMaybe @Int >>= print。
readMaybe @Int 替换为(readMaybe :: String -> Maybe Int)。
readMaybe x 是这样,但我没有指定它的类型。我指定了 readMaybe 的类型。
Control.Monad 中了解>=> 和<=<。它们非常适合无点单子的东西。