-7

Which is not value of the Bin data types as defined below?

data Bin = B Bin | C [ Int]

a) C [ ]

b) B ( B C [ 2])

c) B ( C [ 1..5])

d) B (B (B (C[2,3])))

Will Ness
  • 62,652
  • 8
  • 86
  • 167

2 Answers2

2

To easily answer such questions yourself, you need to comfortably understand Haskell's algebraic data type definitions:

  -- v  a type being defined
data Bin = 
           B  Bin 
        -- ^  ^ the type of the argument to the data constructor `B`
        -- ^ the name of the data constructor function `B`:  B :: Bin -> Bin
        --          (read: B is of type Bin -> Bin, i.e. a function
        --                 taking a Bin type value and producing a Bin type value)
         | C  [Int]
        -- ^  ^ the type of the argument to the data constructor `C`
        -- ^ the name of the data constructor function `C`:  C :: [Int] -> Bin
        --          (read: C is of type [Int] -> Bin, i.e. a function
        --                 taking a list of Int values and producing a Bin type value)

This means, we can create a piece of data of type Bin by using either one of two ways:

  • First, we can call a function named B with one argument, a value of type Bin.
  • Second, we can call a function named C with one argument, a value of type [Int], a list of ints.

The second way is simple and clear: just use any list of ints, like C [1] or C [4,3,2]

x1 :: Bin        -- read: `x1` is of type `Bin`
x1 = C [1]       -- or,

But what about the first? We need to use a value of type Bin as the argument:

x1 = B x2

but where can we get x2? We are creating a Bin, and it wants us to give it a Bin? Is this a vicious circle?

No! For we have the second way of creating a Bin value:

x2 = C [2]    -- x1 = B (C [2])

But we could well use the first one here as well:

x2 = B x3     -- x1 = B (B x3)

and what about x3? By the same token,

x3 = C [3]    -- x1 = B (B (C [3]))   -- or,
x3 = B x4     -- x1 = B (B (B x4))

and

x4 = C [4]    -- x1 = B (B (B (C [4])))   -- or,
x4 = B x5     -- x1 = B (B (B (B x5)))

See? A valid value of the type Bin consists of a nested chain of B constructors, carrying a C [...] inside, at the very bottom of the chain. Right? The data type definition serves as the grammar for producing valid terms of the type.

Now it is easy to answer your questions:

  • C [ ] : - is this a chain of nested B's with C at the bottom? : __

  • B (B C [2]) : - is this a chain of nested B's with C at the bottom? : __

  • B (C [1..5]) : - is this a chain of nested B's with C at the bottom? : __

  • B (B (B (C [2,3]))) : - is this a chain of nested B's with C at the bottom? : __

This repeated application of the same rule is known as recursion, and this data type Bin is thus a recursive data type, with two clauses in its definition: recursive clause, and the base clause.

Which is which?

Will Ness
  • 62,652
  • 8
  • 86
  • 167
1

By using ghci and simply inputing the code snippets you will see which of the values are accepted:

Prelude> data Bin = B Bin | C [ Int]
Prelude> a = C [ ]
Prelude> b = B ( B C [ 2])

<interactive>:3:9: error:
    • Couldn't match expected type ‘[Integer] -> Bin’
                  with actual type ‘Bin’
    • The function ‘B’ is applied to two arguments,
      but its type ‘Bin -> Bin’ has only one
      In the first argument of ‘B’, namely ‘(B C [2])’
      In the expression: B (B C [2])

<interactive>:3:11: error:
    • Couldn't match expected type ‘Bin’
                  with actual type ‘[Int] -> Bin’
    • Probable cause: ‘C’ is applied to too few arguments
      In the first argument of ‘B’, namely ‘C’
      In the first argument of ‘B’, namely ‘(B C [2])’
      In the expression: B (B C [2])
Prelude> c = B ( C [ 1..5])
Prelude> d = B (B (B (C[2,3])))
Daiwen
  • 715
  • 1
  • 4
  • 15