Haskell带括号的newtype

15

我试图理解Monads made difficult中的说明,但是我很难弄清楚以下newtype定义:

newtype (FComp g f) x = FComp { unCompose :: g (f x) }

instance (Functor b c f, Functor a b g) => Functor a c (FComp g f) where
  fmap f (FComp xs) = FComp $ fmap (fmap f) xs

我从未见过一种用括号中的表达式代替类型声明来解释 newtype 的方法。因此,我无法理解 fmap 函数定义的含义。 我也不明白为什么要定义 unCompose 字段但从未使用。我感觉我缺少一些 newtype 的基本语义。

2个回答

16

一个小测试:

newtype (FComp g f) x = FComp { unCompose :: g (f x) }
newtype FComp2 g f x = FComp2 { unCompose2 :: g (f x) }

*Main> :i FComp
newtype FComp g f x = FComp {unCompose :: g (f x)}
        -- Defined at Test.hs:34:10
*Main> :i FComp2
newtype FComp2 g f x = FComp2 {unCompose2 :: g (f x)}
    -- Defined at Test.hs:35:9

所以括号确实不会改变任何东西。它和没有括号一样。

至于uncompose,它只是用来解除newtype包装而不使数据构造函数明确的名称。在你张贴的代码片段中,他们使用模式匹配,但是一个人不希望导出实现细节,因此提供了unCompose以使用FComp的内容。这与data定义中的情况完全相同,只是newtype希望正好有一个字段而不是0..n个字段。


一个人可能希望导出实现细节,至少在只有一件事情可以做的情况下是这样。有时使用解包函数比模式匹配更方便。 - Ben Millwood

11

您可以写成这样:

newtype (FComp g f) x = FComp { unCompose :: g (f x) }

如下所示:

newtype FComp g f x = FComp (g (f x))
unCompose (FComp it) = it

这是因为类型应用具有与普通应用程序相同的语法属性,即:

a b c  = (a b) c

对于值 a、b、c 和类型 a、b、c 都成立。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接