2016-05-07 7 views
0

私はハスケルにとってはとても新しいですが、私はこれについて学ぶのが大好きです。以前使用したこととはまったく異なります。私はモナドについて一冊または二冊読んだことがありますが、それがフローにどのように影響するのですか。私はコードの問題のAdvent of Advent of Codeの問題を解決するために、今はproblem 2にあります。以下のコードを掲載しましたが、正しく動作しますが、きれいに感じることはありません。 fmapを関数の構成で慣用的に使用する

は具体的に私はこれをクリーンアップすることができますどのように思ったんだけど:

main = getContents >>= (return . sum . (fmap getSquareFootage) . lines) >>= print

私はそのような行で関数合成とFMAPと>>=を混合好きではない、私はそれは難しい読むことを見つけます。同じ結果を達成するための慣用的な方法はありますか?私はまた、すべてのハスケルスタイルのアドバイスには開いています、私は本当にこれについて話をする誰も持っていない、ありがとう!

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 

答えて

5

それは純粋な関数として:return . f >>= qはモナド法によってq . fに相当します。

main = getContents >>= print . sum . (fmap getSquareFootage) . lines 

私は.の固定性がinfixl 1 >>=よりも高いことを使用しました。固定性といえば、関数呼び出しがすでに中点に囲まれている場合、関数呼び出しを括弧で囲む必要はありません!あなたのリストに特化されているので、fmapの代わりにmapを使用することができます(これは味の問題です)。

main = getContents >>= print . sum . map getSquareFootage . lines 

IMOも悪くないが、命令が混乱していると主張できる。あなたは

import Control.Arrow 

main = getContents >>= (lines >>> map getSquareFootage >>> sum >>> print) 
+0

恐ろしい感謝を好む場合は、

main = print . sum . map getSquareFootage . lines =<< getContents 

または左から右に、それはすべてが右から左にすることができます!私はこの1つが個人的に好きです: main = print。合計。 getSquareFootageをマップします。私は誤って、 'print'は' a - > IO() 'の代わりに' IO a - > IO() 'を持っていると誤解しました。 –

2

だけでなく、私がやるのブロックにこれを置く:あなたはあなただけのプリコンポーズ、だけ別のものに結果を供給するために矢印Kleisliの終わりにreturnを可能性が使用している場合

main = do 
    ls <- lines <$> getContents 
    let s = sum $ map getSquareFootage ls 
    print s 
関連する問題