Новый тип Haskell с круглыми скобками

Я пытаюсь понять объяснение в Монады, сделанные трудными, и мне сложно определить следующее определение 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 определен, но никогда не используется. Я чувствую, что мне не хватает базовой семантики нового типа.

Ответы

Ответ 1

Вы можете написать это:

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.

Ответ 2

Небольшой тест:

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.