我想我会尝试有趣的 Representable-functors 包为给定的函子定义 Monad
和 Comonad
实例data Pair a = Pair a a
,用Bool
表示;正如我之前关于向量 monad 的问题的回答中提到的。
我注意到的第一件事是,为了使我的类型成为可表示的实例,我不仅应该定义制表符和索引,还应该确保我的类型是 Indexable
、Distributive
、Keyed
、Apply
、Applicative
的实例,和函子类型类。好了,好了,index
就完成了Indexable
的定义,Apply
的<.>
函数就可以了使用Applicative
中的<*>
;需要一个 Functor 实例也就不足为奇了。尽管如此,我对 Keyed
和 Distributive
的实例表示怀疑。
data Pair a = Pair a a
deriving (Show,Eq)
instance Functor Pair where
fmap f (Pair x y) = Pair (f x) (f y)
type instance Key Pair = Bool
instance Keyed Pair where
mapWithKey f (Pair x y) = Pair (f False x) (f False y)
instance Indexable Pair where
index (Pair x _) False = x
index (Pair _ y) True = y
instance Applicative Pair where
pure a = Pair a a
Pair f g <*> Pair x y = Pair (f x) (g y)
instance Apply Pair where
(<.>) = (<*>)
instance Distributive Pair where
collect f x = Pair (getL . f <$> x) (getR . f <$> x)
where getL (Pair x _) = x
getR (Pair _ y) = y
instance Representable Pair where
tabulate f = Pair (f False) (f True)
我的 mapWithKey
定义借用了 Keyed
的 []
实例的定义:尽管我不明白为什么 0
每次迭代都使用它。我对 Pair
的每个术语都使用了类似的 False
。
当我通过定义 Monad
和 Comonad
实例得出结论时,我发现 Bool
需要 Semigroup
定义 >Extend
,以及 Comonad
的 Monoid
定义。我遵循 Either
的 Semigroup
实例,它与 (||)
同构,并为 False
选择mempty
:
instance Monad Pair where
return = pureRep
(>>=) = bindRep
instance Monoid Bool where
mempty = False
mappend = (||)
instance Semigroup Bool where
(<>) = mappend
instance Extend Pair where
extend = extendRep -- needs Bool Semigroup
instance Comonad Pair where
extract = extractRep -- needs Bool Monoid
那么,我是否正确、惯用地满足了 Representable
类的要求?
I thought I'd try the intriguing Representable-functors package to define a Monad
and Comonad
instance for the functor given by data Pair a = Pair a a
which is representable by Bool
; as mentioned in the answer to my earlier question on the vector monad.
The first thing I noticed was that to make my type an instance of Representable
, I should not only define tabulate
and index
, but also ensure my type is an instance of the Indexable
, Distributive
, Keyed
, Apply
, Applicative
, and Functor
type classes. Well, ok, index
completes the definition of Indexable
, and the <.>
function of Apply
can use <*>
from Applicative
; and it shouldn't be a surprise that a Functor
instance is required. Nevertheless, I am doubtful of my instances for Keyed
and Distributive
.
data Pair a = Pair a a
deriving (Show,Eq)
instance Functor Pair where
fmap f (Pair x y) = Pair (f x) (f y)
type instance Key Pair = Bool
instance Keyed Pair where
mapWithKey f (Pair x y) = Pair (f False x) (f False y)
instance Indexable Pair where
index (Pair x _) False = x
index (Pair _ y) True = y
instance Applicative Pair where
pure a = Pair a a
Pair f g <*> Pair x y = Pair (f x) (g y)
instance Apply Pair where
(<.>) = (<*>)
instance Distributive Pair where
collect f x = Pair (getL . f <gt; x) (getR . f <gt; x)
where getL (Pair x _) = x
getR (Pair _ y) = y
instance Representable Pair where
tabulate f = Pair (f False) (f True)
My mapWithKey
definition borrows from that of the []
instance for Keyed
: though I don't understand why 0
was used there for every iteration. I have similarly used False
for each term of Pair
.
As I concluded by defining the Monad
and Comonad
instances, I discovered that Bool
requires a Semigroup
definition for Extend
, and a Monoid
definition for Comonad
. I follow the Semigroup
instance for the Either
, which is isomorphic to (||)
, and choose False
for mempty
:
instance Monad Pair where
return = pureRep
(>>=) = bindRep
instance Monoid Bool where
mempty = False
mappend = (||)
instance Semigroup Bool where
(<>) = mappend
instance Extend Pair where
extend = extendRep -- needs Bool Semigroup
instance Comonad Pair where
extract = extractRep -- needs Bool Monoid
So then, have I met the requirements of the Representable
class correctly, and idiomatically?
发布评论
评论(1)
是的,你有。尽管您的
Keyed
实例已关闭。或者甚至更简单
,类似
给定
index
和tabulate
,您可以使用Representable
模块中的各种fooRep
方法来提供所有其他超类的定义。Extend
和Comonad
定义实际上并不是可表示
要求的一部分。不过它们也被包含在内,因为可表示意味着您与函数同构,这使您能够重复使用“指数”Comonad
(又名 cowriter,或 追踪 comonad) 也成为一个Comonad
,只要你的表示有一些幺半群。但这不是必需的,主要是因为我无法将其限制为所涉及的类型。您可能想删除
Bool
的Semigroup
和Monoid
,而只需手动实现extend
和extract
。这很容易。另外,此类型是 由 rel="noreferrer">representable-tries 包,其中包含许多其他实例。
并且,
表明正如您猜测的那样,有 4 个可能的幺半群,如果您只想要一个扩展实例,则有 8 个半群可用。
Yes you have. Though your instance for
Keyed
is off.or even easier
and similarly
Given
index
andtabulate
you can use the variousfooRep
methods in theRepresentable
module to provide definitions for all of the other superclasses.The
Extend
andComonad
definitions, are not actually part of the requirements to beRepresentable
. They are included though, because being representable means you are isomorphic to a function, which enables you to recycle the definition for the "exponential"Comonad
(aka cowriter, or Traced comonad) to become aComonad
as well, given some monoid on your representation. This isn't required though, mainly because I can't constrain it to hold given the types involved.You may want to drop the
Semigroup
andMonoid
forBool
though and just hand implementextend
andextract
. It is easy enough.Also, this type is provided by the representable-tries package, which includes a number of other instances.
And,
shows that as you surmised there are the 4 possible monoids you surmised and if you only want an extend instance, there are 8 semigroups available.