我对Haskell很陌生,但我喜欢学习它,它与我以前用过的所有东西都有所不同。我已经在Monads上读了一两本书,以及它们如何影响流量,但我仍然有点麻烦。为了让我更好地完成优秀的代码问题,现在我在problem 2,我已经在下面发布了我的代码并且它正常运行,但是没有#39;感觉尽可能干净。
特别是我想知道如何清理它:
main = getContents >>= (return . sum . (fmap getSquareFootage) . lines) >>= print
我不喜欢在这样的行中混合函数组合和fmap AND >>=
,我觉得很难阅读。是否有更惯用的方法来实现相同的结果?我也对任何和所有Haskell风格的建议持开放态度,我真的没有人可以谈论这个,谢谢!
TLDR;我如何惯用地组合fmap,.
和>>=
?
import Data.List.Split (splitOn)
main :: IO ()
main = getContents >>= (return . sum . (fmap getSquareFootage) . lines) >>= print
getSquareFootage :: String -> Int
getSquareFootage box = area dims + slack dims
where dims = read <$> splitOn "x" box
slack = minimum . sides
sides [l, w, h] = [l*w, w*h, h*l]
area [l, w, h] = 2*l*w + 2*w*h + 2*h*l
答案 0 :(得分:5)
如果您在Kleisli箭头末尾使用return
仅将结果提供给另一个,您可以将其预分解为纯函数:return . f >>= q
等效于{{1根据monad法则。
q . f
我已经使用main = getContents >>= print . sum . (fmap getSquareFootage) . lines
的固定度高于.
。说到固定性:你永远不需要用parens包围函数调用,如果它们已经被中缀包围了!由于您的专业列表,您可以使用infixl 1 >>=
代替map
(虽然这是一个品味问题)。
fmap
IMO并不算太糟糕,尽管可能有人认为订单令人困惑。你可以从右到左,
main = getContents >>= print . sum . map getSquareFootage . lines
或从左到右,如果您愿意
main = print . sum . map getSquareFootage . lines =<< getContents
答案 1 :(得分:2)
好吧,我会把它放到一个do块中:
main = do
ls <- lines <$> getContents
let s = sum $ map getSquareFootage ls
print s