23

I'm using Haskell and trying to write the following:

data Scale s = Scale s s

However, I want to make it so that s must be something that of the Num type class, like Int or Double. Is that possible to do using Haskell and GHC?

3
  • 3
    This is possible, but is almost never what you should do. It is generally much better to put the Num s constraint only at the functions that actually need the it. Commented Nov 27, 2016 at 5:03
  • 1
    Alec, all of my functions using the scale will need the num constraint. Commented Nov 27, 2016 at 5:12
  • @AviCaspe There are very good reasons not to do this. The answer contains one, but there are others. You should really consider just putting the constraints where they are needed. Commented Nov 27, 2016 at 5:47

3 Answers 3

41

Yes:

{-# LANGUAGE GADTs #-}
data Scale s where
    Scale :: Num s => s -> s -> Scale s

However, it's generally considered best practice not to do this. Instead, put the Num constraint only on the functions that use Scales and need the Num constraint. Being relaxed about such constraints allows you to temporarily break the invariant where appropriate; e.g. it's common to wish for a Functor instance for such a type, which is impossible if you constrain the constructor as above.

Sign up to request clarification or add additional context in comments.

Comments

9

I had a similar situation with Point type. But I thought not about constraints, I thought about how to do generalizing element type of my point. Then I understood if I'll have point type like this data Point a = Point a a then I can do it instance of Functor, Applicative, Foldable and Traversable. And I'll can design function by standart general way. For example:

dist :: Floating a => Point a -> Point a -> a
dist a b = sqrt $ sum $ (^2) <$> ((-) <$> a <*> b)

And I had question. What is going on? :) If I add constraint (as you asked) I would not can design by this way and I would need to implement a lot of functions like pointSub.

So, there is something to think about :)

2 Comments

Indeed, you can even make a Monad instance for such a type.
Yes, I known, you are right. But I thing it is not intrestiing for this example :)
1

What about this:

data Scale' s = Scale s s
type Scale = Scale' Int Int

I did not try this, I do not know Haskell that well, just (mostly) reading about it, but it seems reasonable, isn't it? 🤔

2 Comments

This certainly is reasonable, but it's quite different from what the OP was asking about.
I think it solves the main issue hidden behind the question though.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.