このコード (または一般に、複数の入力を持つコード) をどのように削減/簡素化できますか?
do
sex <- askSex
name <- askName
sayHello sex name
この場合、すでに非常に短いですが、複数の入力になると、乱雑に見えます。次のようなことを行う方法はありますか:
sayHello askSex askName
?
このコード (または一般に、複数の入力を持つコード) をどのように削減/簡素化できますか?
do
sex <- askSex
name <- askName
sayHello sex name
この場合、すでに非常に短いですが、複数の入力になると、乱雑に見えます。次のようなことを行う方法はありますか:
sayHello askSex askName
?
もし、あんたが
import Control.Applicative -- for <$> and <*>
import Control.Monad -- for join
あなたは書ける
join $ sayHello <$> askSex <*> askName
あなたの例では、2 つのパラメーターのみを取得していますが、これは大きなメリットではありません。ただし、パラメーターの数が多い場合は、コードをより明確にすることができます。
join $ doSomething <$> getFirst <*> getSecond <*> getThird <*> getForth
これは、ApplicativeFunctorsにとって素敵な時間です。
import Control.Applicative -- at the top of your module before any functions
hello "Male" name = "Hi, " ++ name ++ ", that's a cool name."
hello "Female" name = "Hello, " ++ name ++ ", that's a pretty name."
greet = hello <$> askSex <*> askName >>= putStrLn
これは、私が今日あなたに与えた以前の回答と少し同じようfmap
に機能しますが、あなたがここに持っているように、より多くの議論のために。
私のような関数hello
をアプリケーションファンクターで使用すると、IOコードを残りのコードから分離するのに役立ちます。これは非常に良い習慣です。毎回ではhello
なく、書くようにしてください。sayHello
厄介なことに、フーグルはこれについて簡単な答えを持っていません。これは と呼ばれbind2
ます。入力が 1 つしかない関数の場合は=<<
、私が と呼ぶものの中置バージョンである を使用できますbind1
。
sayHello =<< askName
しかし、複数の入力の場合、運が悪いです。何らかの理由で、標準ライブラリはこれを提供しません:
bind2 :: Monad m => (a -> b -> m c) -> m a -> m b -> m c
bind2 f mx my = do
x <- mx
y <- my
f x y
...
bind2 sayHello askSex askName
もちろん、自分で定義することもできます。