Why does this expression have a valid type?

Viewed 197

Banging around in ghci, I happened to notice that the expression (*) 1 [1..5] apparently has a valid type.

:t (*) 1 [1..5]
(*) 1 [1..5] :: (Enum t, Num [t], Num t) => [t]

Apparently it is a list with several type constraints, including Num [t] which looks impossible to me, like it should give an error.

How is this the type of the expression? Why does ghci's :t command not give an error here?

3 Answers

This pattern of idiomatic/applicative lifting exists as Data.Monoid.Ap where Ap [] a specifies lifting operations with pure, fmap and liftA2: (+) = liftA2 (+):

>> :set -XDerivingVia
>> :set -XStandaloneDeriving
>>
>> import Data.Monoid (Ap(..))
>>
>> deriving via Ap [] a instance Num a => Num [a]
>>
>> 1 * [1..5]
[1,2,3,4,5]
>> [100,200] * [1..5]
[100,200,300,400,500,200,400,600,800,1000]

The behaviour for lists is derived via Ap [] a. You get different applicative behaviour through ZipList

>> import Control.Applicative (ZipList(..))
>> 
>> deriving via Ap ZipList a instance Num a => Num [a]
>>
>> 1 * [1..5]
[1,2,3,4,5]
>> [100,200] * [1..5]
[100,400]
Related