Chris Okasaki <[EMAIL PROTECTED]> wrote
| Many of you have run across the problem with
| newtypes that, although it is very cheap to
| coerce between the newtype and the base type, it
| can be very expensive to coerce between, say,
| a list of the newtype and a list of the base type.
| Stephanie Weirich and I are working on a proposal
| for the Haskell Workshop addressing this problem,
| and we would welcome any feedback from the community.
|
| [..]
Simon Peyton-Jones <[EMAIL PROTECTED]> responded
PJ> 1. Personally, I've never actually been bitten by this problem.
PJ> Have you? In other words, how practically important is it?
Let us try:
newtype Int1 = Int1 Int deriving (Eq,Ord,Show,Read)
newtype Int2 = Int2 Int1 deriving (Eq,Ord,Show,Read)
instance Num Int1 where (Int1 n)+(Int1 m) = Int1 (n+m)
fromInteger n = Int1 $ fromInteger n
instance Num Int2 where
(Int2 x)+(Int2 y) = Int2 (x+y)
fromInteger n = Int2 $ Int1 $ fromInteger n
main = let ns = [1..55000] :: [Int]
n1s = map Int1 ns
n2s = map Int2 n1s
s = sum ns
s1 = sum n1s
s2 = sum n2s
in putStr $ shows s2 "\n"
In ghc-4.06, -O s1 costs 10 times more than s,
s2 costs same as s1.
All right, probably, newtype is not guilty.
Because the compiler has not right to treat (+) as strict on Int1
(unlike for Int).
Right?
PJ> 2. More substantially, you describe your solution as lightweight,
PJ> [..]
PJ> So I have an alternative suggestion: provide 'cast' in the language.
PJ>
PJ> That is, if e :: t
PJ> then (cast e) :: s
PJ>
PJ> for any type s that has the same representation as t.
PJ>
PJ> So I need to add some rules saying what it means to 'have the
PJ> same representation' but that's pretty easy. And there's no problem
PJ> with nested types.
PJ>
PJ> What made me think about this is that GHC internally has exactly such
PJ> a thing (it's called 'coerce' rather than 'cast'). Newtype constructors
PJ> are compiled into applications of 'coerce', and similarly pattern matching.
PJ> [..]
I wonder whether I understand at all what newtype is for.
Why could the programmer need to define a copy of a type, but not a
synonym?
I see only one reason. Because one needs to define some instances
differently than for the base type.
Also the Haskell-98 Report, does not it specify that newtype is only
for tagging a new label to the thing preserving the physical
representation?
And if the conversion in this case is only tagging/untagging of a
label, why the language has to introduce `cast' for this? `cast' is
derived automatically by the compiler. The user has not to mention
it, nor to write rules for it, the rules for the cast optimization
are hidden in the compiler too.
What I am missing?
And I do not understand, why Haskell does not support `deriving' for
all the instances (user's too), at least, for newtype.
When the user writes
class C a where c :: a -> a
instance C Int where c = (+2)
newtype Int1 = Int1 Int deriving(Eq,Ord,Num,C),
is not it clear automatically how Num, C are defined?
Further, for
data D a = D ...
if the user had defined for a <--> D a the castings
f :: a -> D a,
f' :: D a -> a
(reciprocally inverse ones),
could the compiler understand what does this mean
...= D...deriving ((C by maps (f,f')),...)
?
Generally, the feature is important for a good style.
This is porting the category instances listed in `deriving'
isomorphically via the explicitly given maps. It allows to skip the
explicit operation definitions for new domain.
I mathematics, they say like this,
"let the operations +,*,/,0,1 on D' be induced from D by the
bijective map f".
I had wrote of all this before, at least, 2 times.
There was no reply.
Probably, there are some details in this business that I do not
foresee.
------------------
Sergey Mechveliani
[EMAIL PROTECTED]