类型类“介于”之间吗?类别和箭头有意义吗?
通常,您会遇到类似 Applicative
的东西,但没有 pure
,或者类似 Monad
的东西,但没有 return
。 semigroupoid 包通过 Apply
和 Bind< 涵盖了这些情况/代码>。现在,我在
Arrow
方面遇到了类似的情况,我无法定义有意义的 arr
函数,但我认为其他函数非常有意义。
我定义了一个包含函数的类型,它是反向函数:
import Control.Category
data Rev a b = Rev (a -> b) (b -> a)
reverse (Rev f g) = Rev g f
apply (Rev f _) x = f x
applyReverse (Rev _ g) y = g y
compose (Rev f f') (Rev g g') = Rev ((Prelude..) f g) ((Prelude..) g' f')
instance Category Rev where
id = Rev Prelude.id Prelude.id
(.) x y = compose x y
现在我无法实现 Arrow
,但更弱的东西:
--"Ow" is an "Arrow" without "arr"
class Category a => Ow a where
first :: a b c -> a (b,d) (c,d)
first f = stars f Control.Category.id
second :: a b c -> a (d,b) (d,c)
second f = stars Control.Category.id f
--same as (***)
stars :: a b c -> a b' c' -> a (b,b') (c,c')
...
import Control.Arrow
instance Ow Rev where
stars (Rev f f') (Rev g g') = Rev (f *** g) (f' *** g')
我认为我无法实现 &&& 的等效项;
,因为它被定义为 f &&& g = arr (\b -> (b,b)) >>>>> f *** g
和 (\b -> (b,b))
是不可逆的。不过,您认为这个较弱类型的类有用吗?从理论角度来看这是否有意义?
Often you have something like an Applicative
without pure
, or something like a Monad
, but without return
. The semigroupoid package covers these cases with Apply
and Bind
. Now I'm in a similar situation concerning Arrow
, where I can't define a meaningful arr
function, but I think the other functions would make perfect sense.
I defined a type that holds a function and it's reverse function:
import Control.Category
data Rev a b = Rev (a -> b) (b -> a)
reverse (Rev f g) = Rev g f
apply (Rev f _) x = f x
applyReverse (Rev _ g) y = g y
compose (Rev f f') (Rev g g') = Rev ((Prelude..) f g) ((Prelude..) g' f')
instance Category Rev where
id = Rev Prelude.id Prelude.id
(.) x y = compose x y
Now I can't implement Arrow
, but something weaker:
--"Ow" is an "Arrow" without "arr"
class Category a => Ow a where
first :: a b c -> a (b,d) (c,d)
first f = stars f Control.Category.id
second :: a b c -> a (d,b) (d,c)
second f = stars Control.Category.id f
--same as (***)
stars :: a b c -> a b' c' -> a (b,b') (c,c')
...
import Control.Arrow
instance Ow Rev where
stars (Rev f f') (Rev g g') = Rev (f *** g) (f' *** g')
I think I can't implement the equivalent of &&&
, as it is defined as f &&& g = arr (\b -> (b,b)) >>> f *** g
, and (\b -> (b,b))
isn't reversable. Still, do you think this weaker type class could be useful? Does it even make sense from a theoretical point of view?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这种方法在“往返:可逆编程的箭头”中进行了探讨: http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.153.9383
正是出于以下原因你遇到的情况是,这是一种糟糕的方法,没有得到更广泛的采用。最近,Tillmann Rendel 提出了一种令人愉快的可逆语法方法,用部分同构代替双箭头 ( http://www.informatik.uni-marburg.de/~rendel/rendel10invertible.pdf)。它已打包在 hackage 上供人们使用和玩:http://hackage.haskell。 org/package/invertible-syntax
也就是说,我认为没有
arr
的箭头具有一定的意义。我只是不认为这样的东西是捕获可逆函数的合适工具。编辑:还有 Adam Megacz 的 Generalized Arrows (http://www.cs.berkeley.edu/~megacz/garrows/)。这些对于可逆编程可能也没有什么用处(尽管基本类型类似乎确实是可逆的),但它们确实在 arr 太强的其他情况下有用,但其他箭头操作可能有意义。
This approach was explored in "There and Back Again: Arrows for invertible programming": http://citeseer.ist.psu.edu/viewdoc/summary?doi=10.1.1.153.9383
For precisely the reasons you're running into, this turned out to be a bad approach that wasn't picked up more widely. More recently, Tillmann Rendel produced a delightful approach to invertible syntax that substituted partial isomorphisms for biarrows ( http://www.informatik.uni-marburg.de/~rendel/rendel10invertible.pdf ) . This has been packaged up on hackage for folks to use and play with: http://hackage.haskell.org/package/invertible-syntax
That said, I think an arrow without
arr
makes a certain amount of sense. I just don't think that such a thing is an appropriate vehicle to capture invertible functions.Edit: There's also Adam Megacz's Generalized Arrows (http://www.cs.berkeley.edu/~megacz/garrows/). These are maybe not useful for invertible programming either (though the basic typeclass does seem to be inveritble), but they do have uses in other situations where
arr
is too strong, but other arrow operations may make sense.从类别理论的角度来看,
Category
类型类描述了任何类别,其箭头可以在 Haskell 中通过类型构造函数直接描述。几乎任何您想要在此基础上构建的附加功能(以新的原始箭头或箭头构建函数的形式)在某种程度上都将有意义,如果您可以使用总函数来实现它。唯一需要注意的是,增加表达能力可能会破坏其他要求,就像arr
经常发生的情况一样。您的可逆函数的具体示例描述了一个所有箭头都是同构的类别。令人震惊的是,Edward Kmett 已经在 Hackage 上实现了这一点。
arr 函数大致相当于从 Haskell 函数到 Arrow 实例的函子(在范畴论意义上),使对象保持不变(即类型参数)。简单地从
Arrow
中删除arr
会给你...其他东西,它本身可能不是很有用,至少不添加arr fst< 的等价物/code> 和
arr snd
作为原语。我相信添加
fst
和snd
的原语以及(&&&)
可以从两个输入构建一个新箭头,应该为您提供一个包含产品的类别,从理论角度来看这是绝对合理的,并且与您使用的可反转箭头的原因你已经找到了。From a Category Theory standpoint, the
Category
type class describes any category whose arrows can be describedn straightforwardly in Haskell by a type constructor. Almost any additional feature you want to build on top of this, in the form of new primitive arrows or arrow-building functions, will make sense to some extent if you can implement it using total functions. The only caveat is that adding expressive power can break other requirements, as often happens witharr
.Your specific example of invertible functions describes a category where all arrows are isomorphisms. In a shocking twist of the completely and utterly expected, Edward Kmett already has an implementation of this on Hackage.
The
arr
function roughly amounts to a functor (in the category theory sense) from Haskell functions to theArrow
instance, leaving objects the same (i.e., the type parameters). Simply removingarr
fromArrow
gives you... something else, which is probably not very useful on its own, without at least adding the equivalents ofarr fst
andarr snd
as primitives.I believe that adding primitives for
fst
andsnd
, along with(&&&)
to build a new arrow from two inputs, should give you a category with products, which is absolutely sensible from a theoretical point of view, as well as not being compatible with the invertible arrows you're using for the reasons you've found.