适用于没有仿函数的人

ale*_*tor 10 haskell ffi functor applicative

我的类型Image基本上是一个浮点数的c数组.可以轻松创建诸如map :: (Float -> Float) -> Image -> Image或之类的功能zipWith :: (Float -> Float -> Float) -> Image -> Image -> Image.

但是,我有一种感觉,也可以在这些函数之上提供看起来像应用实例的东西,允许更灵活的像素级操作,如((+) <$> image1 <*> image2)((\x y z -> (x+y)/z) <$> i1 <*> i2 <*> i3).然而,天真的方法失败了,因为Image类型不能包含浮点数以外的东西,因此无法实现fmap.

怎么能实现呢?

pig*_*ker 15

阅读评论,我有点担心这里的大小已经不足了.尺寸不匹配时是否有明智的行为?

与此同时,您可以通过以下方式合理地做些事情.即使您的数组不容易变为多态,您也可以创建这样的Applicative实例.

data ArrayLike x = MkAL {sizeOf :: Int, eltOf :: Int -> x}

instance Applicative ArrayLike where
  pure x                 = MkAL maxBound  (pure x)
  MkAL i f <*> MkAL j g  = MkAL (min i j) (f <*> g)
Run Code Online (Sandbox Code Playgroud)

(爱好者会注意到我已经(Int ->)使用了(maxBound,min)monoid 引起的应用产品.)

你能做一个干净的通信吗?

imAL :: Image -> ArrayLike Float
alIm :: ArrayLike Float -> Image
Run Code Online (Sandbox Code Playgroud)

通过投影和制表?如果是这样,你可以编写这样的代码.

alIm $ (f <$> imAL a1 <*> ... <*> imAL an)
Run Code Online (Sandbox Code Playgroud)

此外,如果您希望将该模式包装为重载运算符,

imapp :: (Float -> ... -> Float) -> (Image -> ... -> Image)
Run Code Online (Sandbox Code Playgroud)

它是类型类编程的标准练习!(询问您是否需要更多提示.)

但关键的一点是,包装策略意味着您不需要使用数组结构,以便将功能上层结构放在顶部.

  • 您应该只需要两个实例:arity 0的基本情况(如果需要一个数组输入来限制输出的大小,则为1),以及一个步骤情况.坚持(抱歉代码在评论中很难)......`班级NAry ff fi | ff - > fi,fi - > ff其中{naryHelp ::(ArrayLike(Float - > ff)) - >(Image - > fi); nary ::(Float - > ff) - >(Image - > fi); nary = naryHelp.纯粹的; 实例NAry Float Image其中{naryHelp fi = alIm $ f <*> imal i}; 实例NAry ff fi => NAry(Float - > ff)(Image - > fi)其中{naryHelp fi = naryHelp(f <*> imal i)}` (2认同)

Joh*_*n L 6

您希望如何对图像中的像素执行操作?也就是说((+) <$> image1 <*> image2),为什么你想要在Haskell中执行所有操作并构造一个新的结果图像,还是你必须调用C函数来进行所有处理?

如果是前者,那么Pigworker的答案就是我要采取的方法.

相反,如果需要通过C处理所有图像处理,那么如何创建一个小型DSL来表示操作呢?


Con*_*nal 6

Image如果您将"像素"类型Float从有限和离散域(数组)推广到无限和连续域,那么您将获得更多的组合类型.作为这些概括的演示,请参阅功能图像和相应的示例图像(有限采样)库.其结果是,你得到的情况下Monoid,Functor,Applicative,Monad,和Comonad.此外,这些实例的含义完全由函数的相应实例决定,满足语义类型态射的原理,如论文" 具有类型态射的设计 "一文所述.该论文的第13.2节简要描述了图像.