# 不是Functor / Functor / Applicative / Monad的好例子？

##### 问题描述投票：196回答：5

• 一个不是Functor的类型构造函数。
• 一个类型构造函数，它是一个Functor，但不是Applicative。

##### 5个回答
93

``````newtype T a = T (a -> Int)
``````

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

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

``````newtype T a = T {multidimensional array of a}
``````

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

``````[]
``````

``````Functor :: * -> *
Applicative :: * -> *
``````

``````Arrow :: * -> * -> *
``````

82

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

``````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`是一个空的数据类型。如果你试图用`undefined`来证明它是一个Monoid，我会用`unsafeCoerce`来证明它不是。）

``````newtype Boo x = Boo {boo :: Bool}
``````

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

``````join . return == id
``````

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

67

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

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

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

20

7

## 类型构造函数何时无法具有类型类实例？

1. 无法从类类实现所需方法的类型签名。
2. 可以实现类型签名但不能满足所需的法律。

## 具体的例子

• 一个类型构造函数，由于无法实现类型，因此无法使用仿函数实例： ```data F a = F (a -> Int) ```

• 即使可以实现`fmap`的类型签名，也不是合法仿函数的类型构造函数： ```data Q a = Q(a -> Int, a) fmap :: (a -> b) -> Q a -> Q b fmap f (Q(g, x)) = Q(\_ -> g x, f x) -- this fails the functor laws! ```

• 由于`pure`的类型签名无法实现的合法仿函数不适用：采取Writer monad `(a, w)`并删除`w`应该是monoid的约束。因此，不可能从`(a, w)`构造`a`类型的值。
• 一个不适用的仿函数，因为`<*>`的类型签名无法实现：`data F a = Either (Int -> a) (String -> a)`
• 即使可以实现类型类方法，也不是合法应用程序的仿函数： ```data P a = P ((a -> Int) -> Maybe a) ```

``````instance Functor P where
fmap :: (a -> b) -> P a -> P b
fmap fab (P pa) = P (\q -> fmap fab \$ pa (q . fab))
``````

`<*>`类型签名的唯一可能实现是始终返回`Nothing`的函数：

`````` (<*>) :: P (a -> b) -> P a -> P b
(P pfab) <*> (P pa) = \_ -> Nothing  -- fails the laws!
``````

• 一个`Applicative`而不是`Monad`的仿函数，因为`bind`的类型签名无法实现。

• 一个`Applicative`而不是`Monad`的仿函数，因为即使可以实现`bind`的类型签名，法律也不能满足。

`````` data B a = Maybe (a, a)
deriving Functor

instance Applicative B where
pure x = Just (x, x)
b1 <*> b2 = case (b1, b2) of
(Just (x1, y1), Just (x2, y2)) -> Just((x1, x2), (y1, y2))
_ -> Nothing
``````

`````` join :: Maybe (Maybe (a, a, a), Maybe (a, a, a), Maybe (a, a, a)) -> Maybe (a, a, a)
join Nothing = Nothing
join Just (Nothing, Just (x1,x2,x3), Just (y1,y2,y3)) = ???
join Just (Just (x1,x2,x3), Nothing, Just (y1,y2,y3)) = ???
-- etc.
``````

`???`指出的情况下，似乎很清楚我们不能以任何合理和对称的方式从`Just (z1, z2, z3)`类型的六个不同值中产生`a`。我们当然可以选择这六个值中的一些任意子集，例如，总是采用第一个非空的`Maybe` - 但这不符合monad的定律。返回`Nothing`也不符合法律。

• 一种树状数据结构，即使它与`bind`具有关联性，也不是monad - 但是没有同一性。

`````` data Tr f a = Leaf a | Branch (f (Tr f a))
``````

`````` data Trs f a = Leaf (f a) | Branch (f (Trs f a))
join :: Trs f (Trs f a) -> Trs f a
join (Leaf ftrs) = Branch ftrs
join (Branch ftrstrs) = Branch (fmap @f join ftrstrs)
``````

1. `type M a = Either c (w, a)`，其中`w`是任何幺半群
2. `type M a = m (Either c (w, a))`其中`m`是任何monad和`w`是任何monoid
3. `type M a = (m1 a, m2 a)`，其中`m1``m2`是任何monad
4. `type M a = Either a (m a)`，其中`m`是任何monad

`````` join :: (m1 (m1 a, m2 a), m2 (m1 a, m2 a)) -> (m1 a, m2 a)
join (m1x, m2x) = (join @m1 (fmap fst m1x), join @m2 (fmap snd m2x))
``````

`````` data M m a = Either a (m a)
pure x = Left x
join :: Either (M m a) (m (M m a)) -> M m a
join (Left mma) = mma
join (Right me) = Right \$ join @m \$ fmap @m squash me where
squash :: M m a -> m a
squash (Left x) = pure @m x
squash (Right ma) = ma
``````