Strange Loop 2012
bearophile
bearophileHUGS at lycos.com
Tue Oct 16 14:34:21 PDT 2012
Philippe Sigaud:
> I think it's doable in D, with the usual metaprogramming
> suspects.
But the point is: is it a good idea?
> I read this one too (similar tastes or did you read them all?).
I have read them all, of course.
> I admit being a bit disappointed by the wishy-washy conclusion.
Some people work for a month to create a slides pack for a
conference, and some other people work just few hours.
It was not a rigorous study, it was just a little experiment, so
the "conclusions" are just hints.
More info here, but the F# code is missing:
https://github.com/psnively/types_vs_tests
An almost invisible but significant part of this talk was the
Scala code that verifies the number sequences inside the type
system:
https://raw.github.com/psnively/types_vs_tests/master/src/main/scala/Shapeless.scala
> I use both types and unit tests (in D!),
Python has taught me the importance of unit testing, so I write
tons of unittests in D too (about 2.5 lines of tests for each
line of working code), and they help a lot. Unit tests, tests and
contract programming are all useful to write correct D code, I
use them all at the same time.
But I think idiomatic D code gives less importance to "making
invalid states not representable" compared to certain functional
languages like Haskell (despite D ranges are essentially
type-based things).
As an example, in Haskell there is "newtype" that is the D
"Typedef" done (almost) right.
Here you see an example usage of newtype:
http://rosettacode.org/wiki/Total_circles_area#Haskell:_Analytical_Solution
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
newtype Angle = A Double
deriving (Eq, Ord, Num, Fractional)
aPi = A pi
vAngle :: Vec -> Angle
vAngle (Vec x y) = A (atan2 y x)
aNorm :: Angle -> Angle
aNorm a | a > aPi = a - aPi * 2
| a < -aPi = a + aPi * 2
| otherwise = a
By itself "newtype Angle = A Double" is very similar to a strong
typedef of Angle as a double. But then you can't do much with an
Angle. To solve this problem Angle derives (using the
GeneralizedNewtypeDeriving compiler extension, that has some
troubles if used in some cases) the Eq, Ord, Num, Fractional type
classes. This means that this Angle becomes able to support code
like "a - aPi * 2" and the result is another Angle.
Maybe it's possible to do something like this in D.
Currently the Phobos Typedef is almost unusable (is someone using
it?).
If you want another example look at Phobos Nullable compared to
the Maybe of Haskell. Maybe is fully safe, very Handy and it's
used all the time in Haskell. It's defined in the Prelude as:
data Maybe a = Nothing | Just a deriving (Eq, Ord, Read, Show)
Plus some helpers and extras:
maybe :: b -> (a -> b) -> Maybe a -> b
maybe n f Nothing = n
maybe n f (Just x) = f x
instance Functor Maybe where
fmap f Nothing = Nothing
fmap f (Just x) = Just (f x)
instance Monad Maybe where
(Just x) >>= k = k x
Nothing >>= k = Nothing
return = Just
fail s = Nothing
This little program that shows some important things
std.typecons.Nullable isn't able to do (Maybe of Haskell doesn't
share this limits/problems):
import std.stdio, std.algorithm, std.typecons;
alias Nullable!(int, -1) Position;
void foo(int[] a, Position pos) /*nothrow*/ { // allow this to be
nothrow
if (pos.isNull) {
return;
} else {
a[pos] = 10; // perform no nullness test here,
optimization
}
}
void bar(int[] a, Position pos) {
a[pos] = 10; // compile-time error here?
}
void main() {
auto data = [1, 2, 3, 4, 5];
auto p = Position(countUntil(data, 7));
foo(data, p);
writeln(data);
}
Functional languages make the usage of types more handy so it's
simpler to use them to make invalid states unrepresentable.
Bye,
bearophile
More information about the Digitalmars-d
mailing list