簡體   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