8

Haskell で 2 つのモナド アクションを順番に作成し、2 番目のモナドによって生成された値を破棄し、両方のアクションに引数を渡したいと考えています。現在、次のような do ブロックを使用しています。

ask = do
  result <- getLine
  putStrLn result
  return result

これをもう少しポイントフリーできちんと書きたいと思っていたので、これを試しました:

ask' = getLine <* putStrLn

ただし、これは型チェックさえ行わず、問題は<*最初のアクションの結果を 2 番目のアクションに転送しないことです。アクションを連鎖させたいのですが>>=、結果は変えません。タイプは である必要があります(a -> m b) -> (a -> m c) -> (a -> m b)が、Hoogleでは適切な結果が得られません。この関数構成を実現する演算子は何でしょうか?

4

3 に答える 3

9

傾向として、2 つの異なる場所で 1 つの値を使用する場合、無意味なスタイルを押し付けるよりも、明確なブロックで名前を付ける方がおそらく良い考えです。do

情報の流れをさまざまなアクションに分割するという抽象的な概念は、Haskeller では矢印として知られるデカルトのモノイド カテゴリによって捉えられます。あなたの場合、基本的にKleisli カテゴリで作業しています。IO

import Prelude hiding (id)
import Control.Arrow

ask' :: Kleisli IO () String
ask' = Kleisli (\()->getLine) >>> (putStrLn &&& id) >>> arr snd

そのようなコードを書くのは良い考えではないと思います。

于 2015-12-08T17:59:20.987 に答える
2

完全を期すために、この特定のケース ( ) モナドでは、この目的でIO悪用することもできます。bracket

bracket getLine putStrLn return

doしかし、これは元の-notation ブロックよりもはるかに読みにくくなるため、強く思いとどまらせます。

すでに述べたように、この特定のケースでは、結果に名前を付けるのが最善の方法のようです。

Haskell では do 記法を避けるべきですか?も参照してください。

于 2015-12-09T17:58:42.460 に答える
2

Haskell で 2 つのモナド アクションを順番に作成し、2 番目のモナドによって生成された値を破棄し、両方のアクションに引数を渡したいと考えています。

これは私には a のように聞こえますReader— 関数型r -> m aは と同型ReaderT r m aであり、モナドはrすべての「穴」に同じ値を暗黙的に差し込むことによって機能します。たとえば、次のようになります。

import Control.Applicative
import Control.Monad.Reader

example :: IO String
example = getLine >>= discarding putStrLn

discarding :: Monad m => (a -> m b) -> a -> m a
discarding action = runReaderT (ReaderT action *> ask)

必要な演算子は次のようなものです。

action `thingy` extra = action >>= discarding extra

しかしもちろんdiscarding、より単純な実装があります。

discarding :: Applicative f => (a -> f b) -> a -> f a
discarding action a = action a *> return a

…というわけで、これは本当にコードゴルフだと思います。しかし、これが大規模な一般的なパターンである、より複雑なプログラムでは、試してみる価値があるかもしれません。基本的に、あなたが持っている場合:

a0 :: r -> m a0
a1 :: r -> m a1
   .
   .
   .
an :: r -> m an

すると、次のようになります。

ReaderT a0 :: ReaderT r m a0
ReaderT a1 :: ReaderT r m a1
   .
   .
   .
ReaderT an :: ReaderT r m an

その後:

runReaderT (ReaderT a0 <* ReaderT a1 <* ... <* ReaderT an) :: r -> m a0
于 2015-12-09T01:46:29.670 に答える