Data & newtype differences. Today: strictness

Hello, I had for long thought that data and newtype were equivalent, but then I spotted some differences when it comes to strictness. Those can be summed up as: data Test = Test Int newtype TestN = TestN Int pm (Test _) = 12 -- Strict (pm undefined = undefined) pm2 t = t `seq` 12 -- Strict pmN (TestN _) = 12 -- Non strict (pm undefined = 12) pmN2 t = t `seq` 12 -- Strict When I think about it, pm and pmN are logical, as newtype layers are removed by the compiler and then do not exist at runtime. Some would maybe expected pmN2 to behave just like pmN (as I don't 'seq' the inner Int but the outer TestN), but if you follow the same logic (TestN layer doesn't exist at runtime), then you ask to evaluate the inner Int. This can however be misleading when you use an opaque type, can't it? As you don't know if it's declared using data or newtype... These make me think that pattern matching against a newtype is always lazy (irrefutable). Am I right? Is there some litterature expliciting in a less empiric way than I did the differences like this between data and newtype? I've never come against such documentation through all my learning of Haskell, yet I think it's an important point.

* Yves Parès
These make me think that pattern matching against a newtype is always lazy (irrefutable). Am I right?
Yes.
Is there some litterature expliciting in a less empiric way than I did the differences like this between data and newtype? I've never come against such documentation through all my learning of Haskell, yet I think it's an important point.
See the Haskell report, section 3.17.2 "Informal Semantics of Pattern Matching" [1]. In particular, this paragraph: The irrefutable patterns are as follows: a variable, a wildcard, N apat where N is a constructor defined by newtype and apat is irrefutable (see Section 4.2.3), var@apat where apat is irrefutable, or of the form ~apat (whether or not apat is irrefutable). All other patterns are refutable. [1]: http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-600003.17... -- Roman I. Cheplyaka :: http://ro-che.info/

Yves Parès wrote:
Is there some litterature expliciting in a less empiric way than I did the differences like this between data and newtype? I've never come against such documentation through all my learning of Haskell, yet I think it's an important point.
Roman Cheplyaka wrote:
See the Haskell report, section 3.17.2 "Informal Semantics of Pattern Matching" [1].
And section 4.2.3 of the report [2] addresses exactly your points very explicitly: "A type created by newtype differs from an algebraic datatype in that... The following examples clarify the differences between data (algebraic datatypes), type (type synonyms), and newtype (renaming types)..." Regards, Yitz [1] http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-600003.17... [2] http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-740004.2...

Big sum up of everything:
If TestN is a newtype constructor, then
'TestN undefined' and 'undefined' are exactly the same thing.
2012/1/22 Yitzchak Gale
Is there some litterature expliciting in a less empiric way than I did
Yves Parès wrote: the
differences like this between data and newtype? I've never come against such documentation through all my learning of Haskell, yet I think it's an important point.
Roman Cheplyaka wrote:
See the Haskell report, section 3.17.2 "Informal Semantics of Pattern Matching" [1].
And section 4.2.3 of the report [2] addresses exactly your points very explicitly:
"A type created by newtype differs from an algebraic datatype in that... The following examples clarify the differences between data (algebraic datatypes), type (type synonyms), and newtype (renaming types)..."
Regards, Yitz
[1] http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-600003.17... [2] http://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-740004.2...

* Yves Parès
Big sum up of everything:
If TestN is a newtype constructor, then 'TestN undefined' and 'undefined' are exactly the same thing.
To be precise, the former is a type-restricted version of the latter. -- Roman I. Cheplyaka :: http://ro-che.info/

Thanks, that's clearer to me now. It confirmed my thoughts:
Matching the pattern con pat against a value, where con is a constructor defined by newtype, depends on the value: - If the value is of the form con v, then pat is matched against v. - If the value is ⊥, then pat is matched against ⊥.
Put shorter:
newtype TestN = TestN Int
TestN x = undefined
Then x = undefined.
Which means you cannot make a boxed type out of un unboxed one using
newtype. That makes sense.
2012/1/22 Roman Cheplyaka
* Yves Parès
[2012-01-22 11:32:30+0100] These make me think that pattern matching against a newtype is always lazy (irrefutable). Am I right?
Yes.
Is there some litterature expliciting in a less empiric way than I did the differences like this between data and newtype? I've never come against such documentation through all my learning of Haskell, yet I think it's an important point.
See the Haskell report, section 3.17.2 "Informal Semantics of Pattern Matching" [1].
In particular, this paragraph:
The irrefutable patterns are as follows: a variable, a wildcard, N apat where N is a constructor defined by newtype and apat is irrefutable (see Section 4.2.3), var@apat where apat is irrefutable, or of the form ~apat (whether or not apat is irrefutable). All other patterns are refutable.
[1]: http://www.haskell.org/onlinereport/haskell2010/haskellch3.html#x8-600003.17...
-- Roman I. Cheplyaka :: http://ro-che.info/

Yves Parès
I had for long thought that data and newtype were equivalent, but then I spotted some differences when it comes to strictness.
data Test = Test Int newtype TestN = TestN Int
Interesting. I'd thought that data Test = Test !Int and newtype Test = Test Int would be equivalent, but here you (well, I had to add the ! myself) show a situation where they're not. I guess pm (Test _) = 12 is the same as pm = \x -> case x of Test _ -> 12 which perhaps makes it clearer why it breaks on undefined... -k -- If I haven't seen further, it is by standing in the footprints of giants

An interesting use case for this is that while
data Void = Void Void
has infinitely many values (undefined, Void undefined, Void (Void
undefined) etc), the newtype version
newtype Void = Void Void
has only one, bottom. This is a way to define the empty datatype
without extensions.
Erik
On Tue, Jan 24, 2012 at 11:25, Ketil Malde
Yves Parès
writes: I had for long thought that data and newtype were equivalent, but then I spotted some differences when it comes to strictness.
data Test = Test Int newtype TestN = TestN Int
Interesting. I'd thought that
data Test = Test !Int
and
newtype Test = Test Int
would be equivalent, but here you (well, I had to add the ! myself) show a situation where they're not.
I guess
pm (Test _) = 12
is the same as
pm = \x -> case x of Test _ -> 12
which perhaps makes it clearer why it breaks on undefined...
-k -- If I haven't seen further, it is by standing in the footprints of giants
_______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
participants (5)
-
Erik Hesselink
-
Ketil Malde
-
Roman Cheplyaka
-
Yitzchak Gale
-
Yves Parès