Как проверить закон гомоморфизма аппликативного экземпляра?

Я делаю упражнения из Typeclassopedia; в Applicative раздел, я пишу ZipList"s pure и проверьте, следует ли Applicative Законы.

Я проверил:

  • закон об идентичности
  • обменный закон
  • составной закон

Но когда я пытаюсь проверить закон "гомоморфизма", я обнаруживаю, что GHCi не получает результат как MZipList,

Я думаю, что это потому, что я скучаю по назначению pure к моему Applicative тип класс. Как я могу запустить pure функция без <*> это к Applicative немедленно?

Вот MZipList определения и экземпляры классов:

newtype MZipList a = MZipList { getZipList :: [a] }
    deriving (Show)

instance Functor MZipList where
  fmap gs x = pure gs <*> x

instance Applicative MZipList where
  pure a= MZipList (repeat a)
  (MZipList gs) <*> (MZipList xs) = MZipList (zipWith ($) gs xs)

Когда я проверяю закон "Обмен", например:

*Main> (MZipList [(*2),(*3),(*4)]) <*> pure (2)
MZipList {getZipList = [4,6,8]}
*Main> pure ($ 2) <*> (MZipList [(*2),(*3),(*4)])
MZipList {getZipList = [4,6,8]}

Но когда я проверяю закон "гомоморфизма", MZipList"s pure не называется:

*Main> pure (*2) <*> pure 2
4
*Main>  pure ((*2) 2)
4
*Main>

Это почему?

1 ответ

Что такое pure?

pure это просто функция, чтобы "вставить" объект внутри определенного Applicative монада. Например в:

test :: [Int]
test = pure 1 -- [1]

мы вставляем 1 в список монада, что приводит к синглтон [1], Если вы уже читали о Monad класс, то pure в основном так же, как return (если ты не волнуешься).

Ваш экземпляр Applicative Кажется, работает нормально.

Ваши тесты

При запуске команд в GHCi, вы в основном в IO монада, которая также является Applicative, В общем, pure x возвращает IO (type of x),

В:

pure (*2) <*> pure 2

вы "кладете" (*2) в IO объект, затем положить 2 в IO объект, и, наконец, вызов <*> как определено в instance Applicative IO,

Вы не тестируете свой MZipList пример.

Во втором примере вы просто звоните:

pure ((*2) 2)

Если вы помните, (*2) 2 просто относится (*2) в 2таким образом действительно выполняет 2 * 2, Итак, ваш звонок на самом деле:

pure 4

который в GHCi (по-прежнему в контексте IO монада) возвращает IO Int объект.

Как правильно проверить

Чтобы проверить закон "гомоморфизма", вам просто нужно дать компилятору небольшую подсказку о том, какой тип вы действительно хотите:

Так что вместо:

pure (*2) <*> pure 2

вы бы написали:

pure (*2) <*> (pure 2 :: MZipList Int)

Живая демо

Другие вопросы по тегам