破壊的な事業者を構成するためのより良いインタフェース、第2部

StackOverflow https://stackoverflow.com/questions/6069015

  •  07-09-2020
  •  | 
  •  

質問

私の以前の問題 OpenCV演算子の作成について起きている。

私は、一種の合成方法で破壊的なバイナリ操作を構成することを可能にする新しいインターフェースを考えました:

newtype IOP a b = IOP (a -> IO b)

instance Category IOP where
    id = IOP return
    (IOP f) . (IOP g)  = IOP $ g >=> f

(&#&) :: IOP (Image c d) e -> IOP (Image c d) f 
             -> IOP (Image c d) (Image c d,Image c d)
(IOP f) &#& (IOP g) = IOP $ op
    where 
        op i = withClone i $ \cl -> (f i >> g cl >> return (i,cl))

runIOP (IOP f) img = withClone img f 
.

これを使って、「ガウス演算子の差し引き」を簡単に表現できます。

subtract  :: IOP (Image c d, Image c1 d1) (Image c d)
mulScalar :: d -> IOP (Image c d) (Image c d)
subtractScalar :: d -> IOP (Image c d) (Image c d)
gaussian  :: (Int, Int) -> IOP (Image GrayScale D32) (Image GrayScale D32)

(gaussian (11,11) &#& id) >>> subtract >>> mulScalar 5
.

私にとっては、意味が最適ではありませんが、減算後に何らかの操作が必要になる場合は、クローニングされた画像も再利用できるようになります。しかし、それはまだ完全に純粋でオプション化されていないバージョンの許容可能な代替案のようです:

mulScalar 5 $ gaussian (11,11) img `subtract` img
-- Or with nicer names for the operators
5 * gaussian (11,11) img - img
.

質問

  1. これは最初の場所で合理的な構造ですか?
  2. 前の質問
  3. 操作を実行するには、「画像内の最小値を検索」、画像からそれを差し引き、その範囲を範囲に乗算します(すなわち、max-min)。 '
  4. 代わりにこれらを複数の質問に分割する必要がありますか?
役に立ちましたか?

解決

ハンマルのコメントからの継続的なもので、IOPを完全に避けて、Kleisli組成を開始するだけです。私はImageOpを明確にするためにタイプの同義語として維持しました。また、私は常にユニットを返すように専門とし、それに応じて他の種類の署名を変更し、それに応じて他の種類の署名を変更し、変異関数(戻りユニット)とクローインメント関数(新しい値を返す)と、変異関数を適用する関数apOpを変更しました。突然変異を簡単に連鎖できるように変換値を返します。

type ImageOp c d -> Image c d -> IO ()

(&#&) :: ImageOp c d -> ImageOp c d -> (Image c d) -> IO (Image c d, Image c d)
f &#& g = \i -> withClone i $ \cl -> f i >> g cl >> return (i,cl)

apOp :: ImageOp c d -> Image c d -> IO (Image c d)
apOp iop x = fmap x (iop x)

subtract  ::  Image c d ->  ImageOp c1 d1
mulScalar :: d -> ImageOp (Image c d)
subtractScalar :: d -> ImageOp (Image c d)
gaussian  :: (Int, Int) -> ImageOp GrayScale D32

myFun = (gaussian (11,11) &#& id) >=> (\(x,y) -> apOp (subtract x) y) >=> apOp (mulScalar 5) 

--pointfree
myFun = (gaussian (11,11) &#& id) >=> uncurry (apOp . subtract) >=> apOp (mulScalar 5) 
.

編集 あなたがそれを気に入っているならば、あなたは次のように&#&をきちんと書き込むことができます:

f &#& g = uncurry (liftM2 (,)) . (apOp f &&& withClone (apOp g))
.

どのように思う、このスタイルのための良い議論はかなり表現的であると思います。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top