繁体   English   中英

如何为这种数据类型实例化 Functor?

[英]How can I instantiate Functor for this data type?

如何将以下数据类型实例化为 Functor?

data LiftItOut f a = LiftItOut (f a)
data Parappa f g a = DaWrappa (f a) (g a)
data IgnoreOne f g a b = IgnoringSomething (f a) (g b)
data Notorious g o a t = Notorious (g o) (g a) (g t)

声明本身不是很清楚,在右侧成员的括号内,是 function 应用程序(我从未见过,只有基本类型构造函数)? 我是 haskell 的新手,我只是想了解基础知识。

请编译器向您展示如何操作。 使用命令行标志-ddump-deriv ,启用DeriveFunctor语言扩展,并将deriving Functor放在每个类型定义的末尾,然后编译器将为每个类型打印 Functor 实例:

==================== Derived instances ====================
Derived class instances:
  instance GHC.Base.Functor g =>
           GHC.Base.Functor (Main.Notorious g o a) where
    GHC.Base.fmap f_aK1 (Main.Notorious a1_aK2 a2_aK3 a3_aK4)
      = Main.Notorious a1_aK2 a2_aK3 (GHC.Base.fmap f_aK1 a3_aK4)
    (GHC.Base.<$) z_aK5 (Main.Notorious a1_aK6 a2_aK7 a3_aK8)
      = Main.Notorious a1_aK6 a2_aK7 ((GHC.Base.<$) z_aK5 a3_aK8)
  
  instance forall k (f :: k -> *) (g :: * -> *) (a :: k).
           GHC.Base.Functor g =>
           GHC.Base.Functor (Main.IgnoreOne f g a) where
    GHC.Base.fmap f_aK9 (Main.IgnoringSomething a1_aKa a2_aKb)
      = Main.IgnoringSomething a1_aKa (GHC.Base.fmap f_aK9 a2_aKb)
    (GHC.Base.<$) z_aKc (Main.IgnoringSomething a1_aKd a2_aKe)
      = Main.IgnoringSomething a1_aKd ((GHC.Base.<$) z_aKc a2_aKe)
  
  instance (GHC.Base.Functor f, GHC.Base.Functor g) =>
           GHC.Base.Functor (Main.Parappa f g) where
    GHC.Base.fmap f_aKf (Main.DaWrappa a1_aKg a2_aKh)
      = Main.DaWrappa
          (GHC.Base.fmap f_aKf a1_aKg) (GHC.Base.fmap f_aKf a2_aKh)
    (GHC.Base.<$) z_aKi (Main.DaWrappa a1_aKj a2_aKk)
      = Main.DaWrappa
          ((GHC.Base.<$) z_aKi a1_aKj) ((GHC.Base.<$) z_aKi a2_aKk)
  
  instance GHC.Base.Functor f =>
           GHC.Base.Functor (Main.LiftItOut f) where
    GHC.Base.fmap f_aKl (Main.LiftItOut a1_aKm)
      = Main.LiftItOut (GHC.Base.fmap f_aKl a1_aKm)
    (GHC.Base.<$) z_aKn (Main.LiftItOut a1_aKo)
      = Main.LiftItOut ((GHC.Base.<$) z_aKn a1_aKo)

这看起来有点凌乱,但清理起来相当简单:

data LiftItOut f a = LiftItOut (f a)
instance Functor f => Functor (LiftItOut f) where
    fmap f (LiftItOut a) = LiftItOut (fmap f a)

data Parappa f g a = DaWrappa (f a) (g a)
instance (Functor f, Functor g) => Functor (Parappa f g) where
    fmap f (DaWrappa a1 a2) = DaWrappa (fmap f a1) (fmap f a2)

data IgnoreOne f g a b = IgnoringSomething (f a) (g b)
instance Functor g => Functor (IgnoreOne f g a) where
    fmap f (IgnoringSomething a1 a2) = IgnoringSomething a1 (fmap f a2)

data Notorious g o a t = Notorious (g o) (g a) (g t)
instance Functor g => Functor (Notorious g o a) where
    fmap f (Notorious a1 a2 a3) = Notorious a1 a2 (fmap f a3)

还值得注意的是,您的LiftItOutApIdentityT同构,而您的ParappaProduct同构。

你有

data  LiftItOut h a  =  MkLiftItOut    (h a)       -- "Mk..." for "Make..."
      -------------     -----------    ------
      new type,         data           type of the data constructor's
      defined here       constructor    one argument (one field)

这意味着ha是一种可以作为MkLiftItOut参数的事物类型。 例如, Maybe Int (即h ~ Maybea ~ Int )、 [(Float,String)] (即h ~ []a ~ (Float,String) )等。

h , a是类型变量——意思是,它们可以被任何特定类型替换,这样整个句法表达式才有意义。

这些句法表达式包括MkLiftItOut x ,它是LiftItOut ha类型的事物,前提是xha类型的事物; LiftItOut ha是一种类型; ha这是一种可以作为MkLiftItOut的参数出现的事物。 因此我们可以在我们的程序中

v1 = MkLiftItOut [1,2,3]     ::  LiftItOut  []    Int
v2 = MkLiftItOut (Just "")   ::  LiftItOut  Maybe String
v3 = MkLiftItOut Nothing     ::  LiftItOut  Maybe ()
.....

等等然后我们有

ghci> :i Functor
class Functor (f :: * -> *) where
  fmap :: (a -> b) -> f a -> f b
  (<$) :: a -> f b -> f a
..........

这意味着Functor f => fa是一种变量可以引用的事物类型,例如

v4  = Just 4     :: Maybe   Int
v41 =      4     ::         Int

v5  = [4.4, 5.5] :: []      Float
v51 =  4.4       ::         Float
v52 =       5.5  ::         Float

v6  = (1,"a")    :: ((,) Int)  String  -- or simpler, `(Int, String)`
v61 =    "a"     ::            String

v7  = (\x -> 7)  :: ((->) Int) Int     -- or simpler, `Int -> Int`

这里a是事物的类型, fa是事物的类型, f是当给定事物的类型时变成事物的类型的类型; 等等。没有任何东西可以被本身具有类型f的变量引用。

以上所有f都是Functor类型类的实例。 这意味着在图书馆的某处有定义

instance Functor Maybe   where ....
instance Functor []      where ....
instance Functor ((,) a)  where ....
instance Functor ((->) r) where ....

请注意,我们总是有fa f特别是可以由不止一种成分组成,但a总是某种类型。

因此,在这种情况下,我们必须有

instance Functor (LiftItOut h) where ....

(......为什么?一定要说服自己;看看上述所有陈述如何适用并且是正确的)

那么实际的定义一定是

   -- fmap :: (a -> b) -> f           a -> f           b
   -- fmap :: (a -> b) -> LiftItOut h a -> LiftItOut h b
   fmap       g       (MkLiftItOut  x )  =  (MkLiftItOut  y )
     where
     y = ....

特别是,我们将有

    --     g :: a -> b     --   x :: (h a)     --   y :: (h b)

我们甚至不知道h是什么。

我们如何解决这个问题? 当我们甚至不知道任何关于ha而不是b的事情时,我们怎么能从ha类型的东西构造一个hb类型的东西呢?

我们不能。

但是如果我们知道h也是一个Functor呢?

instance (Functor h) => Functor (LiftItOut h) where
   -- fmap :: (a -> b) -> (h a) -> (h b)
   -- fmap :: (a -> b) -> (LiftItOut h a) -> (LiftItOut h b)
   fmap       g       (MkLiftItOut  x )  =  (MkLiftItOut  y )
     where
     -- fmap :: (a -> b) -> (h a) -> (h b)
     y = ....

希望你能完成这件事。 并且也做其他类型。 如果没有,请针对您可能遇到任何其他问题的一种类型发布新问题。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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