![](/img/trans.png)
[英]What would be the Functor instance for the following type: newtype F2 x a = F2 ((a -> x) -> a)
[英]Functor instance for (newtype Mu f = InF {outF :: f (Mu f)})
这让我很难过。 如何为newtype Mu f = InF {outF :: f (Mu f)}
编写 Functor 实例
你不能。 为了为某些c
定义实例Functor c
, c
必须是* -> *
类型。 所以在你的情况下, Mu
应该是那种,这意味着它的论点f
必须是那种*
。 但显然情况并非如此,因为您将f
应用于其他事物(对Mu f
)。
更简单地说,如果Mu
是一个仿函数,则可以对任何f
类型的Mu f
值使用fmap
。 但这将允许您将类型参数更改为任何其他类型,例如,通过将函数fmap (const (0 :: Int))
应用于任何Mu f
值,它必须返回一个Mu Int
值。 但是您不能形成这样的值,因为该值的outF
将具有没有意义的Int (Mu Int)
类型。
redneb 很好地解释了为什么Mu
不能成为常规Functor
但您可以为Mu
实现一种类似仿函数的映射操作
{-# LANGUAGE RankNTypes #-}
newtype Mu f = InF {outF :: f (Mu f)}
mumap :: Functor f => (forall a. f a -> g a) -> Mu f -> Mu g
mumap f (InF m) = InF $ f $ fmap (mumap f) m
虽然我不确定它对你的情况有多大用处。 :)
与 user2297560 不同的对Mu
的轻微改写足以承认 Mu 的 Functor 实例:
-- Natural transformations
type g ~> h = forall a. g a -> h a
class HFunctor f where
ffmap :: Functor g => (a -> b) -> f g a -> f g b
hfmap :: (Functor g, Functor h) => (g ~> h) -> (f g ~> f h)
newtype Mu f a = In { unIn :: f (Mu f) a }
instance HFunctor f => Functor (Mu f) where
fmap f (In r) = In (ffmap f r)
这个公式来自 Patricia 和 Neil 的论文Haskell Programming with Nested Types: A Principled Approach 。
正如 redneb 所描述的,仿函数实例必须具有* -> *
种类,这禁止Mu
成为仿函数,因为它的参数f
应用于f (Mu f)
中的参数。
这是所涉及的各种类型的细分。
首先,创建的新类型,在所有应用的参数之后,必须有种类*
。 所以:
Mu f
必须有种类*
。
其次, Mu f
被设置为等于的也必须具有相同的种类。 那是,
InF { outF :: f (Mu f) }
必须有种类*
。
第三, outF
是一个函数,因此必须返回一个完全实现的类型,无论是参数化的还是具体的,即类型*
。 f (Mu f)
是它的返回类型。 所以
f (Mu f)
必须有种类*
。
最后, f
是一种应用类型,因为它出现在f (Mu f)
中。 换句话说,它有一种f_argument_kind -> f_result_kind
用于某种f_argument_kind
和某种f_result_kind
。 此外, f (Mu f)
告诉我们f_argument_kind
和f_result_kind
的种类。 也就是说, f_argument_kind
匹配Mu f
的种类 ( *
), f_result_kind
匹配f (Mu f)
的种类 ( *
)。 所以
f
有种类* -> *
。
将其与已知类型的Mu f
( *
) 结合,我们得到类型构造函数的类型。
Mu
有种类(* -> *) -> *
。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.