这让我很难过。如何为newtype Mu f = InF {outF :: f (Mu f)}
答案 0 :(得分:7)
你做不到。为了为某些Functor c
定义实例c
,c
必须属于* -> *
种类。因此,在您的情况下,Mu
应该属于那种类型,这意味着其参数f
必须属于*
类型。但显然情况并非如此,因为您正在将f
应用于其他内容(Mu f
)。
更简单地说,如果Mu
是一个仿函数,则可以对任何fmap
类型Mu f
的值使用f
。但这可以让您将类型参数更改为任何其他类型,例如,通过将函数fmap (const (0 :: Int))
应用于任何Mu f
值,它必须返回Mu Int
值。但是你不能形成这样的值,因为该值的outF
将具有无效的类型Int (Mu Int)
。
答案 1 :(得分:4)
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
虽然我不确定你的情况会有多大用处。 :)
答案 2 :(得分:0)
对Mu
进行轻微的重新措辞,与user2297560不同,足以接受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。