Reputation: 1092
I am trying to understand how to use the functions defined in the following Haskell code (available here) in Prelude.
module List
where
data List a = Nil
| Cons a (List a)
listLength :: List a -> Int
listLength Nil = 0
listLength (Cons x xs) = 1 + listLength xs
{-
listHead :: List a -> Maybe a
listHead Nil = Nothing
listHead (Cons x xs) = Just x
listTail :: List a -> Maybe (List a)
listTail Nil = Nothing
listTail (Cons x xs) = Just xs
-}
listHead :: List a -> a
listHead (Cons x xs) = x
listTail :: List a -> List a
listTail (Cons x xs) = xs
listFoldl :: (a -> b -> a) -> a -> List b -> a
listFoldl f c Nil = c
listFoldl f c (Cons x xs) = listFoldl f (f c x) xs
listFoldr :: (a -> b -> b) -> b -> List a -> b
listFoldr f c Nil = c
listFoldr f c (Cons x xs) = f x (listFoldr f c xs)
I have loaded it using ghci List.hs
command.
Then following is the way I am trying to use listHead
.
*List> listHead (List 1:2:[])
<interactive>:7:11: Not in scope: data constructor `List'
Or like the following:
*List> listHead ('a':'b':[])
<interactive>:11:11:
Couldn't match expected type `List a0' with actual type `[Char]'
In the first argument of `listHead', namely `('a' : 'b' : [])'
In the expression: listHead ('a' : 'b' : [])
In an equation for `it': it = listHead ('a' : 'b' : [])
Could anyone please explain how to use this code in ghci? Thanks!
Upvotes: 0
Views: 105
Reputation: 120751
The :
operator and the []
construct are specific to Haskell's built-in list type, i.e. you can only use them to construct values of some type [a]
. But the functions you have here don't deal with this standard list type, but with the locally defined List
container. To construct such lists, you need to replace each :
with Cons
and each []
with Nil
. It's complicated a bit by the fact that Cons
is not an infix operator, so you first need to rewrite a:b
as (:) a b
. For example, the [Int]
list 1:2:[]
becomes (:) 1 ((:) 2 [])
, and that is equivalent to Cons 1 (Cons 2 Nil)
.
Those custom-lists can then be fed to any of those functions.
*List> listHead $ Cons 1 (Cons 2 Nil)
1
Of course this is ugly, but that List
type is only introduced for educational purposes. In practice, you would use the standard []
type, or use nicer constructors. For instance, you can define infix constructors like :
yourself:
infixr 6 :&
data List' a = N | a :& List' a
With that you could just do
*List> list'Head $ 1 :& 2 :& N
Alternatively, you could make GHC accept the []
syntax for your custom list type:
{-# LANGUAGE OverloadedLists, TypeFamilies #-}
import GHC.Exts (IsList(..))
instance IsList (List l) where
type Item (List l) = l
fromList [] = Nil
fromList (a:l) = Cons a $ fromList l
And then
*List> listHead [1,2]
1
Upvotes: 3
Reputation: 34398
You are supposed to build your custom List
s using the Cons
and Nil
data constructors that are defined by:
data List a = Nil
| Cons a (List a)
The first error, Not in scope: data constructor `List'
, happened because you can't use List
to build values (List
is a type constructor, and List a
is a type). What you actually want is:
listHead (Cons 1 (Cons 2 Nil)))
The second error, Couldn't match expected type `List a0' with actual type `[Char]'
, happened because you are trying to use the regular list constructors, (:)
and []
, to build List Char
values. You should use Cons
instead of (:)
and Nil
instead of []
.
Upvotes: 2