MC2DX
MC2DX

Reputation: 572

The replicate function implemented by list comprehension

I'm learning Haskell and I have tried to implement the replicate function on my own and below is result of my work:

replicate' :: Enum a => a -> b -> [b]
replicate' a b = [b | _ <- [1..a]]

but during loading script into ghci I got msg:

proginhaskell.hs:152:29:
Could not deduce (Num a) arising from the literal `1'
from the context (Enum a)
  bound by the type signature for
             replicate' :: Enum a => a -> b -> [b]
  at proginhaskell.hs:152:1-34
Possible fix:
  add (Num a) to the context of
    the type signature for replicate' :: Enum a => a -> b -> [b]
In the expression: 1
In the expression: [1 .. a]
In a stmt of a list comprehension: _ <- [1 .. a]

I would like to ask how to repair this problem. Is it correct way to implement replicate function ?

Upvotes: 2

Views: 3500

Answers (2)

daniel gratzer
daniel gratzer

Reputation: 53901

The problem is that you're using the list expression [1..a] that means that we have to be able to treat 1 as the same type as a. The type of 1 is

1 :: Num a => a -- Numbers are actually polymorphic!

So GHC is complaining that you haven't said that a is a Num instance. So you can just add Num to your constraints on a.

replicate' :: (Enum a, Num a) => a -> b -> [b]
replicate' a b = [b | _ <- [1..a]]

As for how good this code is, I'd probably write it with take, but both are fine implementations. If you're curious how it's actually implemented (though with a more restrictive replicate :: Int -> a -> [a])

replicate n x = take n (repeat x)

Upvotes: 5

Pedro Rodrigues
Pedro Rodrigues

Reputation: 1739

From this snippet of code [1..a] the compiler inferes that a should have the same of type as 1. Since 1 is a Num, it follows that a should be of type Num. So instead of Enum a you should have (Enum a, Num a) as your context.

Upvotes: 2

Related Questions