-1

I'm a bit confused with type and newtype. It is said that newtype can contain only one field. I also find a post here.

But still not quite clear.

So if you want to declare different type class instances for a particular type, or want to make a type abstract, you can wrap it in a newtype and it'll be considered distinct to the type-checker, but identical at runtime.

Any example would be helpful. Thank you!

user8314628
  • 1,952
  • 2
  • 22
  • 46
  • Is there something in that other link that is still confusing? If you can expand on what you're not understanding, we might be able to provide more help. For me, I think of using newtypes to wrap anything I want to be specified. For example, instead of passing a bunch of `Text`s around and not knowing which `Text` is an email-y thing and which is a phone-number-y thing, I create two newtypes for `Email` and `Phone` that just wrap text values. – jkeuhlen Jul 31 '18 at 22:40
  • 3
    Here's my rule of thumb. I think beginners should follow it pretty strictly, and intermediate Haskellers should follow it unless there's a reason not to. 1. Don't use `type` at all; it's only useful in very special cases. 2. Use `newtype` whenever there's exactly one constructor and it has exactly one field. 3. Use `data` the rest of the time. – dfeuer Jul 31 '18 at 22:41
  • FYI, the main cases where I think `type` is a reasonable thing: 1. Higher-rank type synonyms: `type f ~> g = forall x. f x -> g x`, `type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t` 2. Type synonyms that expand to constraints, for use in the "wrapper class" pattern: `type FooS a b c = (...,...,...,...); class FooS a b c => Foo a b c; instance FooS a b c => Foo a b c`. 3. Type synonyms that expand to type family applications: `type Reverse xs = RO '[] xs; type family RO acc xs where {RO acc '[] = acc; RO acc (x ': xs) = RO (x ': acc) xs}` – dfeuer Jul 31 '18 at 22:53
  • Please see: https://wiki.haskell.org/Type – AJF Jul 31 '18 at 23:05
  • If you sort a `[Int]` you get the standard increasing order. If you want to use your own order, one option (even if not the only one) is to `newtype MyInt = MyInt Int` and then `instance Ord MyInt where ...` to define a custom order. After that, if you sort `[MyInt]` you'll get the elements sorted by the custom order. Newtypes are often used so that one can "change" (roughly speaking) some predefined class instances. – chi Jul 31 '18 at 23:13

1 Answers1

3

An example usage collected from the quote you posted would perhaps be declaring two Int monoids. There are multiple ways to consider Int a monoid (multiplication or addition), and perhaps you wish to use more than one. You can not define more than one monoid instance for Int, but you can instead create two newtypes and provide separate instances for them.

newtype SumInt = SumInt Int 
newtype ProdInt = ProdInt Int 

instance Monoid SumInt where
  mempty = SumInt 0
  (SumInt a) `mappend` (SumInt b) = SumInt (a + b)

instance Monoid ProdInt where
  mempty = ProdInt 1
  (ProdInt a) `mappend` (ProdInt b) = ProdInt (a*b)
amalloy
  • 89,153
  • 8
  • 140
  • 205
Robert
  • 277
  • 1
  • 16
  • 1
    I think it is worth mentioning as a curiosity (and to help better understand the issue) that Idris does that using 'named implementations' (which Haskell doesn't have) http://docs.idris-lang.org/en/latest/tutorial/interfaces.html#named-implementations – Mika Feiler Aug 01 '18 at 10:03