繁体   English   中英

(newtype Mu f = InF {outF :: f (Mu f)}) 的函子实例

[英]Functor instance for (newtype Mu f = InF {outF :: f (Mu f)})

这让我很难过。 如何为newtype Mu f = InF {outF :: f (Mu f)}编写 Functor 实例

你不能。 为了为某些c定义实例Functor cc必须是* -> *类型。 所以在你的情况下, 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_kindf_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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM