我想知道为什么以下是Pair类型的正确实现。具体来说,为什么Pair b a
而不是Pair a b
?
newtype Pair b a = Pair { getPair :: (a,b) }
为了澄清,Pair a b
不适用于以下内容:
instance Functor (Pair c) where
fmap f (Pair (x,y)) = Pair (f x, y)
我不明白为什么。
除了以下很多很棒的答案之外,我发现在ghci中做了以下有用的事情:
*Main> newtype Pair b a = Pair (a, b) deriving (Show, Eq)
*Main> :t Pair(True, "cat")
Pair(True, "cat") :: Pair [Char] Bool
*Main> newtype Pair a b = Pair (a, b) deriving (Show, Eq)
*Main> :t Pair(True, "cat")
Pair(True, "cat") :: Pair Bool [Char]
答案 0 :(得分:5)
您正在谈论definition in LYAH:
newtype Pair b a = Pair { getPair :: (a,b) }
注意它之前的段落(强调我的):
事实证明,为此编写实例有点困难。使用
Maybe
,我们只说实例Functor Maybe,因为只有一个参数的类型构造函数才能成为Functor的一个实例。 但似乎无法使用(a,b)
执行此类操作,因此类型参数a最终会在我们使用fmap
时更改。为了解决这个问题,我们可以通过第二种类型参数表示元组中第一个组件的类型来新建我们的元组:
因此,在这种情况下,我们希望类型构造函数{{1}中的(底层)对 first 元素的类型是 last 类型}。毕竟,我们想在LYAH的第一个参数上使用Pair
:
fmap
您当然可以将定义更改为-- b
-- |
-- v a isn't here…
instance Functor (Pair c) where
-- but here!
--fmap :: (a -> x) -> Pair c a -> Pair c x
fmap f (Pair (x,y)) = Pair (f x, y)
。但在这种情况下会发生什么?
newtype Pair b a = Pair { getPair :: (a,b) }
请记住,您的基础类型现在是-- a
-- |
-- v b isn't here…
instance Functor (Pair c) where
-- but here! v---- c ----v--------------------------+
--fmap :: (b -> x) -> Pair c b -> Pair c x |
fmap f (Pair (x,y)) = Pair (f x, y) -- |
-- ^^^ uh-oh - that doesn't seem right-+
。但是,在您的(a,b)
实例Functor
现已修复,但您尝试对其应用a
。这不起作用。相反,您必须在第二个条目上使用fmap
,该条目对应于类型构造函数fmap
中的b
:
Pair a b
但此时,我们又回到原来的-- a
-- |
-- v b isn't here…
instance Functor (Pair c) where
-- but here!
--fmap :: (b -> x) -> Pair c b -> Pair c x
fmap f (Pair (x,y)) = Pair (x, f y)
-- ^^^ everything fine now.
个实例。
答案 1 :(得分:0)
newtype Pair a b
和newtype Pair b a
都是正确的(例如,他们键入check)。在后者中,第二个元素的类型首先出现,这是违反直觉的,尽管它可能更适合您的用例。