非Functor / Functor / Applicative / Monad的好例子?

在向某人解释什么是Xtypes的时候,我很难find恰好是X的数据结构的好例子。

所以,我请求例子:

  • 一个不是Functor的types构造函数。
  • 一个types构造函数,它是一个Functor,但不适用。
  • 一个types构造函数是一个应用程序,但不是一个Monad。
  • Monad的types构造函数。

我认为Monad在世界各地都有很多的例子,但是Monad的一个很好的例子是与之前的例子有一些联系,可以完成这个图画。

我寻找相似的例子,仅在属于特定types的重要方面有所不同。

如果有人能够在这个层次结构的某个地方偷偷摸摸地find一个箭头的例子(它在Applicative和Monad之间?),那也太棒了!

一个不是Functor的types构造函数:

 newtype T a = T (a -> Int) 

你可以使用一个逆变函数,但不是一个(协变)函数。 尝试编写fmap ,你会失败。 请注意,逆变函数的版本是相反的:

 fmap :: Functor f => (a -> b) -> fa -> fb contramap :: Contravariant f => (a -> b) -> fb -> fa 

一个types的构造函数是一个函子,但不适用:

我没有一个很好的例子。 Const ,但理想情况下我想要一个具体的非Monoid,我想不出来。 所有types基本上都是数字,枚举,产品,总和或函数。 你可以看到下面的pigworker和我不同意Data.Void是否是Monoid ;

 instance Monoid Data.Void where mempty = undefined mappend _ _ = undefined mconcat _ = undefined 

由于_|_是Haskell中的一个合法值,并且实际上是Data.Void的唯一合法值, Data.Void这符合Monoid规则。 我不确定unsafeCoerce与它有什么关系,因为一旦使用任何unsafe函数,程序就不能保证不会违反Haskell语义。

有关底部( 链接 )或不安全function( 链接 )的文章,请参见Haskell Wiki。

我想知道是否有可能使用更丰富的types系统来创build这样的types构造函数,比如Agda或Haskell以及各种扩展。

一个types构造函数是一个应用程序,但不是一个Monad:

 newtype T a = T {multidimensional array of a} 

你可以用一个类似的东西来制作一个应用程序。

 mkarray [(+10), (+100), id] <*> mkarray [1, 2] == mkarray [[11, 101, 1], [12, 102, 2]] 

但是,如果你使它成为一个monad,你可能会得到一个尺寸不匹配。 我怀疑这样的例子在实践中很less见。

一个Monadtypes的构造函数:

 [] 

关于箭头:

询问箭头在这个层次结构上的位置,就像询问“红色”是什么形状。 注意类的不匹配:

 Functor :: * -> * Applicative :: * -> * Monad :: * -> * 

但,

 Arrow :: * -> * -> * 

我的风格可能会受到我的手机的限制,但是这里却是如此。

 newtype Not x = Kill {kill :: x -> Void} 

不能是一个Functor。 如果是的话,我们会的

 kill (fmap (const ()) (Kill id)) () :: Void 

月亮将由绿色奶酪制成。

与此同时

 newtype Dead x = Oops {oops :: Void} 

是一个函数

 instance Functor Dead where fmap f (Oops corpse) = Oops corpse 

但不能适用,否则我们会有

 oops (pure ()) :: Void 

而绿色则由月亮奶酪制成(实际上可能会发生,但晚些时候才会发生)。

(额外注意: Void ,如Data.Void是一个空的数据types,如果你试图使用undefined来certificate它是一个Monoid,我将使用unsafeCoerce来certificate它不是)。

欢悦,

 newtype Boo x = Boo {boo :: Bool} 

在许多方面是可应用的,例如,像迪克斯特拉所说的那样,

 instance Applicative Boo where pure _ = Boo True Boo b1 <*> Boo b2 = Boo (b1 == b2) 

但它不能是一个单子。 要明白为什么不这样做,要注意回归必须不断地Boo TrueBoo False ,因此

 join . return == id 

不可能持有。

噢,我差点忘了

 newtype Thud x = The {only :: ()} 

是Monad。 滚动你自己的。

飞机赶上…

我相信其他答案错过了一些简单而常见的例子:

一个types的构造函数,它是一个Functor而不是一个Applicative。 一个简单的例子是一对:

 instance Functor ((,) r) where fmap f (x,y) = (x, fy) 

但是如何在不对r施加额外限制的情况下如何定义它的Applicative实例是没有办法的。 特别是,如何为任意r定义pure :: a -> (r, a)是没有办法的。

一个types构造函数是一个应用程序,但不是一个Monad。 一个众所周知的例子是ZipList 。 (这是一个包装列表的新types,为它们提供了不同的Applicative实例。)

fmap以通常的方式定义。 但是pure<*>被定义为

 pure x = ZipList (repeat x) ZipList fs <*> ZipList xs = ZipList (zipWith id fs xs) 

所以pure通过重复给定的值来创build一个无限的列表,并且用一系列值来压缩函数列表 – 将第i个函数应用于第i个元素。 ( []上的标准<*>产生将第i个函数应用到第j个元素的所有可能的组合)。但是如何定义monad没有明智的方法(见这篇文章 )。


箭头如何适合函数/应用/ monad层次结构? 看到成语是没有意义的,箭头是细致的,monad是山姆林德利,菲利普Wadler,杰里米Yallop 混杂 。 MSFP 2008.(他们称之为应用函子习语 。)摘要:

我们重新审视三种计算概念之间的联系:莫吉的单子,休斯的箭,麦克布莱德和帕特森的成语(也称为应用函子)。 我们certificate成语相当于满足types同构A→B = 1→A(A→B)的箭头,单子相当于满足types同构的箭头A→B = A→(1〜 > B)。 此外,成语embedded箭头和箭头embeddedmonad。

一个不是函子的types构造函数的一个很好的例子是Set :你不能实现fmap :: (a -> b) -> fa -> fb ,因为没有额外的约束Ord b你不能构造fb