简体   繁体   中英

Applicative functor laws violation

Excersize from an online course.

Suppose, that for a standard list Applicative functor the <*> operator is defined in a standard way, while pure is changed to

pure x = [x,x]

What laws of Applicative typeclass will be violated?

  • Homomorphism: pure g <*> pure x ≡ pure (gx)
  • Identity: pure id <*> xs ≡ xs
  • Interchange: fs <*> pure x ≡ pure ($ x) <*> fs
  • Applicative-Functor: g <$> xs ≡ pure g <*> xs
  • Composition: (.) <$> us <*> vs <*> xs ≡ us <*> (vs <*> xs)

I created the following file:

newtype MyList a = MyList {getMyList :: [a]}
  deriving Show

instance Functor MyList where
  fmap f (MyList xs) = MyList (map f xs)

instance Applicative MyList where
  pure x = MyList [x,x]
  MyList gs <*> MyList xs = MyList ([g x | g <- gs, x <- xs])

fs = MyList [\x -> 2*x, \x -> 3*x]
xs = MyList [1,2]
x = 1
g = (\x -> 2*x)
us = MyList [(\x -> 2*x)]
vs = MyList [(\x -> 3*x)]

Then I tried:

Homomorphism: pure g <*> pure x ≡ pure (gx)

*Main> pure g <*> pure x :: MyList Integer
MyList {getMyList = [2,2,2,2]}
*Main> pure (g x) :: MyList Integer
MyList {getMyList = [2,2]}

Identity: pure id <*> xs ≡ xs

*Main> pure id <*> xs :: MyList Integer
MyList {getMyList = [1,2,1,2]}
*Main> xs :: MyList Integer
MyList {getMyList = [1,2]}

Interchange: fs <*> pure x ≡ pure ($ x) <*> fs

*Main> fs <*> pure x
[2,3]
*Main> pure ($ x) <*> fs
[2,3]

Applicative-Functor: g <$> xs ≡ pure g <*> xs

*Main> g <$> xs
MyList {getMyList = [2,4]}
*Main> pure g <*> xs
MyList {getMyList = [2,4,2,4]}

Composition: (.) <$> us <*> vs <*> xs ≡ us <*> (vs <*> xs)

*Main> (.) <$> us <*> vs <*> xs
MyList {getMyList = [6,12]}
*Main> us <*> (vs <*> xs)
MyList {getMyList = [6,12]}

Composition shouldn't be violated, because pure is not used here.

It seems that Homomorphism, Identity and Applicative-Functor don't work. But when I select them in the course, it says that the answer is wrong. So, who is the fool: me or the author of the course?

As per @DavidFletcher's comment, using your code, I see different output for the interchange test:

> fs <*> pure x
MyList {getMyList = [2,2,3,3]}
> pure ($ x) <*> fs
MyList {getMyList = [2,3,2,3]}

so you might want to double-check that one.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM