非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 True
或Boo 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
。