1

有关正在发生的事情的解释,请参阅我之前关于编写 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. 我应该把这些分成多个问题吗?
4

1 回答 1

2

继续 hammar 的评论,您可以只使用 kleisli 组合开始,完全避免 IOP。为了清楚起见,我将 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))

我认为,这是一个很好的论据,因为这种风格非常具有表现力。

于 2011-05-20T16:51:28.390 回答