Как проверить закон гомоморфизма аппликативного экземпляра?
Я делаю упражнения из 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)