Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
289 views
in Technique[技术] by (71.8m points)

haskell - Remove type synonym in instance declaration of a contravariant functor

If I define:

class Contravariant f where
    contramap :: (b -> a) -> f a -> f b

type Op r a = (->) a r

And want to define:

instance Contravariant (Op r) where
    contramap f g = g . f

I get the error that instance type must not be synonyms. So I guess i need something akin to:

instance Contravariant ((->) _ r) where
    contramap f g = g . f

Which of course does not work. How can I get this instance of Contravariant to work ?


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

As per the comments, the usual method is to define a newtype. Note that the syntax is much the same as defining a data type, except that you use newtype in place of data and are only permitted one field. In particular, you need a constructor, which is frequently given the same name as the type:

newtype Op r a =   Op      (a -> r)
--      ^^         ^^      ^^^^^^^^
--    newtype  constructor  field

This has the effect of defining a type isomorphic to a -> r but with the type parameter a coming "last" in the full type Op r a, which allows you to define a Contravariant instance for Op r. Note that you'll need to unwrap and wrap the constructor where appropriate:

instance Contravariant (Op r) where
  contramap f (Op g) = Op (g . f)

For additional evidence that this is correct way to do it, note that the definitions in Data.Functor.Contravariant from base are already set up like this, except they've decided to use a field accessor getOp:

-- from the Data.Functor.Contravariant source

newtype Op a b = Op { getOp :: b -> a }

instance Contravariant (Op a) where
  contramap f g = Op (getOp g . f)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...