Haskel and F# comparsion

This is quick introduction to F# and its syntax for Haskell programmers. In this article, you can find essential operations written in both Haskell and F#. So if you have already some experience with Haskell then it will be easy to get into the secrets of F#.

Basics, Functions, Lists, Types and some others…


F# introduction for Haskell programmers

  1. Basics
  2. Functions
  3. Lists
  4. Types
  5. Others

  1. Basics

  2. Comments

    Line and block comments

     Haskell
            ––Haskell line comment
    
            {––
              Haskell block comment
            ––}
          

     F#
            // F# line comment
    
            (*
              F# block comment
            *)
          

    Lists

    List of integers

     Haskell
            [1,2,3,4,5]
          

     F#
            [1;2;3;4;5]
          

    Tuples

    Tuples in F# are the same as in Haskell

     Haskell
            (1,”hello”,’c')
          

     F#
            (1,”hello”,’c')
          

    Boolean operations

     Haskell
            (5 > 3 && “abc” /= “def”) || (”abc” == “abc”)
          

     F#
            (5 > 3 && “abc” <> “def”) || (”abc” = “abc”)
          

    Variables

    Declaring variable str of infered type string

     Haskell
            let str = “abc”
          

     F#
            let str = “abc”
          

    Note: Variables can contain more than just a simple value (e.g. expressions)

    Function composition

    Double filtered even numbers

     Haskell
            (map (\\x -> x * x) . filter (\\x -> x `rem` 2 == 0))
              [1,2,3,4,5]
          

     F#
            ((List.filter (fun x -> x % 2 = 0)) >>
               (List.map (fun x -> x * x))) [1;2;3;4;5] –– [4,16]
          

    Pipes

     F#
            ((List.filter (fun x -> x % 2 = 0)) [1;2;3;4;5] |>
              (List.map (fun x -> x * x)))   // [4;16]
          

    let .. in ..

     Haskell
            let x = 4; y = 2 in x + y
          

     F#
            let x = 4 and y = 2 in x + y
          


  3. Functions

  4. Simple function

    Parameter type inference

     Haskell
            square n = n * n
          

     F#
            let square n = n * n
          

    Simple function

    Parameter type explicitly defined

     Haskell
            square :: Int -> Int
            square n = n * n
          

     F#
            let square (n:int) = n * n
          

    Recursive function, if - else

    Factorial function using ‘if - else’ statement. It is recursive function which must be explicitly marked with rec keyword in F#

     Haskell
            fac :: Int -> Int
            fac n = if n > 1 then n * fac(n-1) else 1
          

     F#
            let rec fac n = if n > 1 then fac n * (n-1) else 1
          

    Recursive function, pattern matching

    Factorial function using pattern matching

     Haskell
            fac :: Int -> Int
            fac 0 = 1
            fac 1 = 1
            fac n = n * fac (n-1)
          

    In F#, keyword function enables using simplified way of pattern matching in functions. Parameters are infered from pattern, they can’t be explicitly defined here.

     F#
            let rec fac = function
                  | 0 | 1 -> 1
                  | n -> n * fac (n-1)
          

    This is an alternative using match for pattern matching with explicitly defined parameter type

     F#
            let rec fac (n:int) = match n with
                                | 0 | 1 -> 1
                                | n -> n * fac (n-1);;
          

    Function as a parameter

    Function requiring a function (int -> int) as a parameter. Implementation of a map function for list of integers

     Haskell
            mapInt :: (Int -> Int) -> [Int] -> [Int]
            mapInt _ []     = []
            mapInt f (x:xs) = f x : mapInt f xs
          

     F#
            let mapInt (f:int -> bool) (xs:int list)
                = match xs with
                | [] -> []
                | (n::ns) -> f n :: mapInt f ns
          


  5. Lists

  6. Simple list

    List of integers

     Haskell
            [1,2,3,4,5]
          

     F#
            [1;2;3;4;5]
          

    Append element to list

     Haskell
            0:[1,2,3,4,5]
          

     F#
            0::[1;2;3;4;5]
          

    Join two lists

     Haskell
            [0,1,2,3] ++ [4,5,6,7]
          

     F#
            [0;1;2;3] @ [4;5;5;6]
          

    List of integers as a function parameter, pattern matching

    Function sumList sums all elements of a list

     Haskell
            sumList :: [Int] -> Int
            sumList []     = 0
            sumList (x:xs) = x + sumList xs
          

    Function parameter infered

     F#
            let rec sumList = function
                      | []      -> 0
                      | (x::xs) -> x + sumList xs
          

    Function parameter explicitly defined

     F#
            let rec sumList (xs:int list) = match xs with
                                  | []      -> 0
                                  | (x::xs) -> x + sumList xs
          

    List of generic values as a function parameter, option (some, none)

    Function hd returns first element of a list, if list is empty returns none

     Haskell
            hd :: [a] -> Maybe a
            hd [] = Nothing
            hd xs = Just (head xs)
          

     F#
            let hd (xs:’a list) = match xs with
                                | []      -> None
                                | (x::xz) -> Some x
          

    List.map

    Double numbers in the list

     Haskell
            map (\\x -> x * 2) [1,2,3,4,5]
          

     F#
            List.map (fun x -> x * 2) [1;2;3;4;5]
          

    List.fold_right

     Haskell
            foldr (\\x y -> x `div` y) 1 [64,8,2]
                –– 64 / (8 / (2 / 1)) = 16
          

     F#
            List.fold_right (fun x y -> x / y) [64;8;2] 1
                // 64 / (8 / (2 / 1)) = 16
          

    List.filter

    Get list including only even numbers

     Haskell
            filter (\\x -> x % 2 == 0) [1,2,3,4,5,6,7,8]
          

     F#
            List.filter (fun n -> n % 2 = 0) [1;2;3;4;5;6;7;8]
          


  7. Types

  8. Simple type

     Haskell
            type strList = [string]
          

     F#
            type strList = string list
          

    Discriminated union type (multiple contructors)

    Binary tree

     Haskell
            –– definition
            data Tree = Node Tree Tree
                      | Leaf
    
            –– usage
            (Node (Node Leaf Leaf) Leaf)
          

     F#
            // definition
            type Tree =
                      | Node of Tree * Tree
                      | Leaf
    
            // usage
            Node (Node (Leaf, Leaf), Leaf)
          

    Discriminated union type in pattern matching

    Function leafCount returns number of leafs in the tree, using Tree type defined in previous example

     Haskell
            leafCount :: Tree -> Int
            leafCount (Node t1 t2)
              = leafCount t1 + leafCount t2
            leafCount Leaf = 1
          

     F#
            let rec leafCount = function
              | Node (t1, t2) -> leafCount t1 + leafCount t2
              | Leaf -> 1
          

    Discriminated union type with generic value

    Binary tree, leafs hold generic values

     Haskell
            –– definition
            data Tree a = Node Tree Tree
                        | Leaf a
    
            –– usage
            (Node (Node (Leaf ‘a’) (Leaf ‘b’)) (Leaf ‘c’))
          

     F#
            // definition
            type ‘a Tree =
                         | Node of ‘a Tree * ‘a Tree
                         | Leaf of ‘a
    
            // usage
            Node (Node (Leaf ‘a’, Leaf ‘b’), Leaf ‘c’)
          

    Discriminated union type with generic value

    Binary tree, leafs hold list of generic values

     Haskell
            –– definition
            data Tree a = Node Tree Tree
                        | Leaf [a]
    
            – usage
            (Node (Node (Leaf [’a',’b'])
                  (Leaf [’b',’c'])) (Leaf [’c',’d']))
          

     F#
            // definition
            type ‘a Tree =
                         | Node of ‘a Tree * ‘a Tree
                         | Leaf of (’a list)
    
            // usage
            Node (Node (Leaf [’a';’b'], Leaf [’b';’c']),
                 Leaf [’c';’d'])
          


  9. Others

  10. Custom operator

    Substraction with non-negative result

     Haskell
            (%%) x y = let res = x - y
                       in if res > 0 then res else 0
    
                       –– 5 %% 2 = 3; 5 %% 8 = 0
          

     F#
            let (%%) x y = let res = x - y
                           in if res > 0 then res else 0
    
                       // 5 %% 2 = 3; 5 %% 8 = 0
          

One Response to “Haskel and F# comparsion”

  1. Lasaro Says:

    Union types are interesting but what if I want to represent a tree with a simple list of lists like [[[l1];[l2]];[l3]]? How can I recursively traverse such a tree in F#?

Leave a Reply