[英]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)
你有
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 ~ Maybe
和a ~ Int
)、 [(Float,String)]
(即h ~ []
和a ~ (Float,String)
)等。
h
, a
是类型变量——意思是,它们可以被任何特定类型替换,这样整个句法表达式才有意义。
这些句法表达式包括MkLiftItOut x
,它是LiftItOut ha
类型的事物,前提是x
是ha
类型的事物; 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 ....
请注意,我们总是有f
和a
。 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
是什么。
我们如何解决这个问题? 当我们甚至不知道任何关于h
、 a
而不是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.