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])))
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])))
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:
B
with one argument, a value of type Bin
.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?
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])))