hubFS: THE place for F#

. . . are you on The Hub?
Welcome to hubFS: THE place for F# Sign in | Join | Help
in Search

Robert's Strange F# Blog

In the key of F#

While I’m aware that my last posting could do with a fair bit of explanation for it to be really useful, I’m not in the mood to do that right now so thought I’d show something cute.

 

I was searching for something work related when I came across this sample in MSDN which I thought was quite cute so I decided to port it to F#. The sample plays “Mary had a Little Lamb” thought the console beeper.

 

Well here it is:

 

type tone =
|    REST
|    GbelowC
|    A  |    Asharp
|    B
|    C  |    Csharp
|    D  |    Dsharp
|    E
|    F  |    Fsharp
|    G  |    Gsharp

type duration =
|    WHOLE
|    HALF
|    QUARTER
|    EIGHTH
|    SIXTEENTH

let convert_tone t  =
    match t with
    |    REST   -> 0
    |    GbelowC   -> 196
    |    A   -> 220  |    Asharp   -> 233
    |    B   -> 247
    |    C   -> 262  |    Csharp   -> 277
    |    D   -> 294  |    Dsharp   -> 311
    |    E   -> 330
    |    F   -> 349  |    Fsharp   -> 370
    |    G   -> 392  |    Gsharp   -> 415

let convert_duration d =
    match d with
    |    WHOLE      -> 1600
    |    HALF       -> 800
    |    QUARTER    -> 400
    |    EIGHTH     -> 200
    |    SIXTEENTH  -> 100
   
let mary =
    [
    B, QUARTER;
    A, QUARTER;
    GbelowC, QUARTER;
    A, QUARTER;
    B, QUARTER;
    B, QUARTER;
    B, HALF;
    A, QUARTER;
    A, QUARTER;
    A, HALF;
    B, QUARTER;
    D, QUARTER;
    D, HALF
    ]

let rec play tune =
    match tune with
    |   head :: tail ->
        begin
        match head with
        |   REST, d    ->  System.Threading.Thread.Sleep(convert_duration d)
        |   t, d    ->  System.Console.Beep(convert_tone t, convert_duration d)
        end;
        play tail
    |   [] -> ()
   
do play mary

 

One thing that is slightly annoying about the sample is that the C# version is a good bit shorter. This is because C# has the concept of enums, that F# does not support. How the reason that F# does not support enums is because they are a bit dodgy, by this I mean C# will allow us to just cast any old int into an enum even if it is not a member of the enum. See what I mean:

 

    class Program
    {
        protected enum Duration
        {
            WHOLE = 1600,
            HALF = WHOLE / 2,
            QUARTER = HALF / 2,
            EIGHTH = QUARTER / 2,
            SIXTEENTH = EIGHTH / 2,
        }

        static void Main(string[] args)
        {
            Duration d = (Duration)1232;
        }
    }

 

F# gives us its union type which is similar to enums but more powerful. However enums do one thing that union type can’t; you can directly associate an integer value with an enum, you can't do this with a union type. However after reflecting on this for a bit maybe this abstraction is a good thing. For example it would be trivial to create anther “convert_tone” function that mapped the tone type to another octave, you could then parameterise the “play” function to accept the a convert_tone function which then allows you to play your tune in any octave you whish. Well with in the limits of the consoles beep functionality!

 

 

Published Thursday, May 18, 2006 11:18 PM by Robert

Comments

 

palevich said:

Ocaml has a feature "Obj.magic" that lets you get at the underlying numerical rep for the tag. I presume F# could support this (or something similar) as well.
May 19, 2006 9:40 PM
 

Robert said:

F# provides a version of “Obj.magic” but it the compiler issues a warning saying it isn’t advisable to use it in F# code. Information about what it does seems a little thin on the ground, but if it lets you get the underlying numerical representation for the tag, I don’t think this would be helpful since there is no way for the programmer to define what the underlying representation is.
May 20, 2006 9:53 PM
Anonymous comments are disabled

About Robert

Robert is a professional computer programmer, who lives in Paris and has worked London, Copenhagen, Amsterdam and Brussels.

This Blog

Post Calendar

<May 2006>
SuMoTuWeThFrSa
30123456
78910111213
14151617181920
21222324252627
28293031123
45678910

Syndication

Powered by Community Server, by Telligent Systems