Reputation: 15959
the other day I wrote a small program to collect a bunch of numbers in a matrix - data Matrix = Matrix [[Int]]
starting at a corner - Corner
and follow a Path - [Direction]
all of the three types are instance of a class Transformable
then i have a function that generates a transformation function, that turns a given corner and direction - to LeftUp
and Right
turnLUR :: Transformable a => (Corner, Direction) -> a -> a
then i use this function to "harvest" all the numbers in the matrix:
harvest :: Matrix → [(Corner,Direction)] → [Int]
harvest _ [] = []
harvest (Matrix []) _ = []
harvest as (cd:csds) = b ++ harvest (Matrix bs) csds' --cd = (Corner,Direction)
where f1 = turnLUR cd -- Matrix -> Matrix
f2 = turnLUR cd -- Corner -> Corner
f3 = turnLUR cd -- Direction -> Direction
Matrix (b:bs) = f1 as -- b = first line of [[Int]]
fcfd (c,d) = (f2 c,f3 d)
csds' = map fcfd csds
Now my question why do I have to write down f1
, f2
and f3
instead of using one function f
three times (keeping DRY in my mind!) - all three types Corners
, Directions
and Matrix
are instances of the class Transformable
.
How would I write that code without - making three versions of the "same" function?
Upvotes: 5
Views: 155
Reputation: 40797
This is because of the monomorphism restriction. Give it an explicit type signature, and you'll be able to reuse the same function each time:
harvest :: Matrix → [(Corner,Direction)] → [Int]
harvest _ [] = []
harvest (Matrix []) _ = []
harvest as (cd:csds) = b ++ harvest (Matrix bs) csds' --cd = (Corner,Direction)
where f :: Transformable a => a -> a
f = turnLUR cd
Matrix (b:bs) = f as -- b = first line of [[Int]]
fcfd (c,d) = (f c,f d)
csds' = map fcfd csds
Alternatively, you can turn it off by putting {-# LANGUAGE NoMonomorphismRestriction #-}
at the top of your file.
The monomorphism restriction isn't well-liked — even GHC's manual refers to it as the dreaded monomorphism restriction — but there are some tricky corner cases, especially related to sharing (see the wiki page I linked for more information), that it avoids. In this case, I'd recommend just adding the type signature.
Upvotes: 11