Error when trying to create a Data.List? - haskell

I am trying to create a list of type Pos (custom) but keep getting the following error:
Not in scope: type constructor or class `List'
Code:
import Data.List
type Pos = (Int, Int)
type PlayList = List Pos
The error comes up on the line where I define my type PlayList.
Any ideas? Using Haskell in EclipseFP

The list type is actually called [], so you'd want
type PlayList = [Pos]
Although you'll often see people write their own list implementation for playing with various techniques as
data List a = Nil | Cons a (List a)
which is isomorphic to (identical to except for name) the actual implementation of
data [a] = [] | a : [a]
Where Nil == [] and Cons == (:).

Related

Trying to add a tuple in front of a list in Haskell but receiving error?

type Name = String
type PhoneNumber = Int
type Person = (Name, PhoneNumber)
type PhoneBook = [Person]
add :: Person -> PhoneBook -> PhoneBook
add (a,b)
add (a,b) ++ []
I'm trying to add an entry in front of the list but its giving me an error
Parse error: module header, import declaration
or top-level declaration expected.
|
30 | add (a,b) : xs
| ^^^^^^^^^^^^^^
where am I going wrong?
You are trying to add a list and a tuple. But ++ is defined for adding lists to lists, not for adding tuples to lists. Haskell is very strict about types, so it won't let you do this.
You should make the tuple a list:
add [(a,b)] ++ []
Or, as was suggesteed by Robin Zigmond in their comment, use the : operator:
add (a,b) : []
You have another issue though - your function definition should contain an = operator:
add (a,b) [] = [(a,b)]
This is how a function is defined in Haskell. On the lefthand side, it tells Haskell wat the inputs are. On the righthand side, it tells Haskell what they should be transformed into.
You may want to refer to Learn You A Haskell : Syntax in Functions for a nice introduction to defining functions in Haskell.
Based on your post you can run the following piece of code:
type Name = String
type PhoneNumber = Int
type Person = (Name, PhoneNumber)
type PhoneBook = [Person]
add :: Person -> PhoneBook -> PhoneBook
add (name, phoneNumber) phoneBook = (name, phoneNumber) : phoneBook
main = print $ add ("xyz", 987) (add ("abcd", 123) [])
which yields:
[("xyz",987),("abcd",123)]

Create type with double symbol

The List type is created with
data [] a = [] | a : [a]
But I can't create my own type with the same structure:
data %% a = %% | a : %a%
error: parse error on input `%%'
The List type is created with
data [] a = [] | a : [a]
No, it isn't. If you look at the source (for GHC; other compilers may do it differently), it says
data [] a = MkNil
but this is just a marker for the compiler (not even this, see chepner's comment). This is because
data [] a = [] | a : [a]
isn't legal syntax in Haskell.
What is true is that list works as if it were defined this way: it's entirely equivalent to
data List a = Nil | Cons a (List a)
except for the names.
Type and constructor names must either be alphanumeric names, starting with uppercase
data MyType a b = K a | L b a
or be symbolic infix operators, starting with :
data a :** b = K a | b :+-& a
Both types above are perfectly isomorphic: we only replaced MyType with the infix :** and L with the infix :+-&.
Also note that infixes must be binary, i.e. take two arguments. Alphanumeric names do not have such constraint (e.g. K above only takes one argument).
List syntax [] is specially handled by the compiler, similarly to (,),(,,),... for tuples. Only : follows the general rule (perhaps incidentally).

Can constraints be enforced on public data types?

I have the following code :
-- A CharBox is a rectangular matrix of characters
data CharBox = CharBox [String]
deriving Show
-- Build a CharBox, ensuring the contents are rectangular
mkCharBox :: [String] -> CharBox
mkCharBox [] = CharBox []
mkCharBox xxs#(x:xs) = if (all (\s -> (length s) == length x) xs)
then CharBox xxs
else error "CharBox must be a rectangle."
The [[Char]] must be rectangular (i.e. all sub-lists must have the same length) for many functions in the module to work properly. Inside the module I'm always using the mkCharBox "constructor" so I don't have to enforce this constraint all the time.
Initially I wanted my module declaration to look like this :
module CharBox (
CharBox, -- No (CharBox) because it doesn't enforce rectangularity
mkCharBox
) where
But like that, users of my module cannot pattern match on CharBox. In another module I do
findWiresRight :: CharBox -> [Int]
findWiresRight (CharBox xs) = elemIndices '-' (map last xs)
And ghci complains: Not in scope: data constructor 'CharBox'
Is it possible to enforce my constraint that CharBoxes contain only rectangular arrays, while still allowing pattern matching ? (Also if this is not possible, I'd be interested in knowing the technical reason why. I find there's usually a lot to learn in Haskell when exploring such restrictions)
It's not possible in vanilla Haskell to both hide the constructors and support pattern matching.
The usual approaches to address this are:
view patterns, essentially, export the pattern matching functions.
or:
move the invariant into the type system via size types.
The simplest solution would be to add an extract function to the module:
extract :: CharBox -> [String]
extract (CharBox xs) = xs
and then use it instead of pattern matching:
findWiresRight :: CharBox -> [Int]
findWiresRight c = elemIndices '-' $ map last $ extract c

Get a list of the instances in a type class in Haskell

Is there a way to programmatically get a list of instances of a type class?
It strikes me that the compiler must know this information in order to type check and compile the code, so is there some way to tell the compiler: hey, you know those instances of that class, please put a list of them right here (as strings or whatever some representation of them).
You can generate the instances in scope for a given type class using Template Haskell.
import Language.Haskell.TH
-- get a list of instances
getInstances :: Name -> Q [ClassInstance]
getInstances typ = do
ClassI _ instances <- reify typ
return instances
-- convert the list of instances into an Exp so they can be displayed in GHCi
showInstances :: Name -> Q Exp
showInstances typ = do
ins <- getInstances typ
return . LitE . stringL $ show ins
Running this in GHCi:
*Main> $(showInstances ''Num)
"[ClassInstance {ci_dfun = GHC.Num.$fNumInteger, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Integer.Type.Integer]},ClassInstance {ci_dfun = GHC.Num.$fNumInt, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Int]},ClassInstance {ci_dfun = GHC.Float.$fNumFloat, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Float]},ClassInstance {ci_dfun = GHC.Float.$fNumDouble, ci_tvs = [], ci_cxt = [], ci_cls = GHC.Num.Num, ci_tys = [ConT GHC.Types.Double]}]"
Another useful technique is showing all instances in scope for a given type class using GHCi.
Prelude> :info Num
class (Eq a, Show a) => Num a where
(+) :: a -> a -> a
(*) :: a -> a -> a
(-) :: a -> a -> a
negate :: a -> a
abs :: a -> a
signum :: a -> a
fromInteger :: Integer -> a
-- Defined in GHC.Num
instance Num Integer -- Defined in GHC.Num
instance Num Int -- Defined in GHC.Num
instance Num Float -- Defined in GHC.Float
instance Num Double -- Defined in GHC.Float
Edit: The important thing to know is that the compiler is only aware of type classes in scope in any given module (or at the ghci prompt, etc.). So if you call the showInstances TH function with no imports, you'll only get instances from the Prelude. If you have other modules in scope, e.g. Data.Word, then you'll see all those instances too.
See the template haskell documentation: http://hackage.haskell.org/packages/archive/template-haskell/2.5.0.0/doc/html/Language-Haskell-TH.html
Using reify, you can get an Info record, which for a class includes its list of instances. You can also use isClassInstance and classInstances directly.
This is going to run into a lot of problems as soon as you get instance declarations like
instance Eq a => Eq [a] where
[] == [] = True
(x:xs) == (y:ys) = x == y && xs == ys
_ == _ = False
and
instance (Eq a,Eq b) => Eq (a,b) where
(a1,b1) == (a2,b2) = a1 == a2 && b1 == b2
along with a single concrete instance (e.g. instance Eq Bool).
You'll get an infinite list of instances for Eq - Bool,[Bool],[[Bool]],[[[Bool]]] and so on, (Bool,Bool), ((Bool,Bool),Bool), (((Bool,Bool),Bool),Bool) etcetera, along with various combinations of these such as ([((Bool,[Bool]),Bool)],Bool) and so forth. It's not clear how to represent these in a String; even a list of TypeRep would require some pretty smart enumeration.
The compiler can (try to) deduce whether a type is an instance of Eq for any given type, but it doesn't read in all the instance declarations in scope and then just starts deducing all possible instances, since that will never finish!
The important question is of course, what do you need this for?
I guess, it's not possible. I explain you the implementation of typeclasses (for GHC), from it, you can see, that the compiler has no need to know which types are instance of a typeclass. It only has to know, whether a specific type is instance or not.
A typeclass will be translated into a datatype. As an example, let's take Eq:
class Eq a where
(==),(/=) :: a -> a -> Bool
The typeclass will be translated into a kind of dictionary, containing all its functions:
data Eq a = Eq {
(==) :: a -> a -> Bool,
(/=) :: a -> a -> Bool
}
Each typeclass constraint is then translated into an extra argument containing the dictionary:
elem :: Eq a => a -> [a] -> Bool
elem _ [] = False
elem a (x:xs) | x == a = True
| otherwise = elem a xs
becomes:
elem :: Eq a -> a -> [a] -> Bool
elem _ _ [] = False
elem eq a (x:xs) | (==) eq x a = True
| otherwise = elem eq a xs
The important thing is, that the dictionary will be passed at runtime. Imagine, your project contains many modules. GHC doesn't have to check all the modules for instances, it just has to look up, whether an instance is defined anywhere.
But if you have the source available, I guess an old-style grep for the instances would be sufficient.
It is not possible to automatically do this for existing classes. For your own class and instances thereof you could do it. You would need to declare everything via Template Haskell (or perhaps the quasi-quoting) and it would automatically generate some strange data structure that encodes the declared instances. Defining the strange data structure and making Template Haskell do this are details left to whomever has a use case for them.
Perhaps you could add some Template Haskell or other magic to your build to include all the source files as text available at run-time (c.f. program quine). Then your program would 'grep itself'...

Type-conditional controls in Haskell

I'm going through the 99 Haskell problems to build my proficiency with the language. On problem 7 ("Flatten a nested list structure"), I found myself wanting to define a conditional behavior based on the type of argument passed to a function. That is, since
*Main> :t 1
1 :: (Num t) => t
*Main> :t [1,2]
[1,2] :: (Num t) => [t]
*Main> :t [[1],[2]]
[[1],[2]] :: (Num t) => [[t]]
(i.e. lists nested at different levels have different data types) it seems like I should be able to write a function that can read the type of the argument, and then behave accordingly. My first attempt was along these lines:
listflatten l = do
if (:t l) /= ((Num t) => [t]) then
listflatten (foldl (++) [] l)
else id l
But when I try to do that, Haskell returns a parse error. Is Haskell flexible enough to allow this sort of type manipulation, do I need to find another way?
1. Use pattern matching instead
You can solve that problem without checking for data types dynamically. In fact, it is very rarely needed in Haskell. Usually you can use pattern matching instead.
For example, if you have a type
data List a = Elem a | Nested [List a]
you can pattern match like
flatten (Elem x) = ...
flatten (Nested xs) = ...
Example:
data List a = Elem a | Nested [List a]
deriving (Show)
nested = Nested [Elem 1, Nested [Elem 2, Elem 3, Nested [Elem 4]], Elem 5]
main = print $ flatten nested
flatten :: List a -> [a]
flatten (Elem x) = [x]
flatten (Nested lists) = concat . map flatten $ lists
map flatten flattens every inner list, thus it behaves like [List a] -> [[a]], and we produce a list of lists here. concat merges all lists together (concat [[1],[2,3],[4]] gives [1,2,3,4]). concat . map flatten is the same as concatMap flatten.
2. To check types dynamically, use Data.Typeable
And if on some rare occasion (not in this problem) you really need to check types dynamically, you can use Data.Typeable type class and its typeOf function. :t works only in GHCI, it is not part of the language.
ghci> :m + Data.Typeable
ghci> typeOf 3 == typeOf "3"
False
ghci> typeOf "a" == typeOf "b"
True
Likely, you will need to use DeriveDataTypeable extension too.
(Sorry about the length—I go a little bit far afield/in excessive depth. The CliffsNotes version is "No, you can't really do what you want because types aren't values and we can't give your function a sensible type; use your own data type.". The first and the fifth paragraph, not counting this one or the code block, explain the core of what I mean by that first part, and the rest of the answer should provide some clarification/detail.)
Roughly speaking, no, this is not possible, for two reasons. The first is the type-dispatch issue. The :t command is a feature (an enormously useful one) of GHCi, and isn't a Haskell function. Think about why: what type would it have? :t :: a -> ?? Types themselves aren't values, and thus don't have a type. It's two different worlds. So the way you're trying to do this isn't possible. Also note that you have a random do. This is bad—do notation is a syntactic sugar for monadic computation, and you aren't doing any of that. Get rid of it!
Why is this? Haskell has two kinds polymorphism, and the one we're concerned with at the moment is parametric polymorphism. This is what you see when you have a type like concat :: [[a]] -> a. That a says that one single definition of concat must be usable for every possible a from now until the end of time. How on earth would you type flatten using this scheme? It's just not possible.
You're trying to call a different function, defined ad-hoc, for different kinds of data. This is called, shockingly, ad-hoc polymorphism. For instance, in C++, you could define the following function:
template <typename T>
void flatten(vector<T>& v) { ... }
template <typename T>
void flatten(vector< vector<T> >& v) { ... }
This would allow you do different things for different types. You could even have template <> void flatten(int) { ... }! You can accomplish this in Haskell by using type classes such as Num or Show; the whole point of a type signature like Show a => a -> String is that a different function can be called for different as. And in fact, you can take advantage of this to get a partial solution to your problem…but before we do, let's look at the second problem.
This issue is with the list you are trying to feed in. Haskell's list type is defined as (roughly) data [a] = [] | a : [a]. In other words, every element of a list must have the same type; a list of ints, [Int], contains only ints, Int; and a list of lists of ints, [[Int]], contains only lists of ints, [Int]. The structure [1,2,[3,4],5] is illegal! Reading your code, I think you understand this; however, there's another ramification. For similar reasons, you can't write a fully-generic flatten function of type flatten :: [...[a]...] -> [a]. Your function also has to be able to deal with arbitrary nesting depth, which still isn't possible with a list. You need [a], [[a]], and so on to all be the same type!
Thus, to get all of the necessary properties, you want a different type. The type you want has a different property: it contains either nothing, a single element followed by the rest of the value, or a nested list of elements followed by the rest of the value. In other words, something like
data NList a = Nil
| a :> NList a
| (NList a) :>> NList a
deriving (Eq, Show)
infixr 5 :>, :>>
Then, instead of the list [1,2,3] == 1 : 2 : 3 : [], you would write 1 :> 2 :> 3 :> Nil; instead of Lisp's (1 (2 3) 4 ()), you would write
1 :> (2 :> 3 :> Nil) :>> 4 :> Nil :>> Nil. You can even begin to define functions to manipulate it:
nhead :: NList a -> Either a [a]
nhead Nil = error "nhead: Empty NList."
nhead (h :> _) = Left a
nhead (h :>> _) = Right a
ntail :: NList a -> NList a
ntail Nil = error "nhead: Empty NList."
ntail (_ :> t) = t
ntail (_ :>> t) = t
Admittedly, you might find this a bit clunky (or perhaps not), so you might try to think about your type differently. Another option, which the Haskell translation of the 99 problems uses, is to realize that everything in a nested list is either a single item or a list of nested lists. This translation gives you
data NestedList a = Elem a
| List [NestedList a]
deriving (Eq, Show)
The two above lists then become List [Elem 1, Elem 2, Elem 3] and List [Elem 1, List [Elem 2, Elem 3], Elem 4, List []]. As for how to flatten them—since you're trying to learn from the 99 problems, that I won't say :) And after all, you seem to have a handle on that part of the problem.
Now, let's return to type classes. I lied a bit when I said that you couldn't write something which took an arbitrarily-nested list—you can, in fact, using type classes and some GHC extensions. Now, before I continue, I should say: don't use this! Seriously. The other technique is almost definitely a better choice. However, this technique is cool, and so I will present it here. Consider the following code:
{-# LANGUAGE MultiParamTypeClasses, FlexibleInstances, UndecidableInstances #-}
class Flattenable f e where
flatten :: f -> [e]
instance Flattenable a a where
flatten = return
instance Flattenable f e => Flattenable [f] e where
flatten = concatMap flatten
We are creating a type class whose instances are the things we can flatten. If we have Flattenable f e, then f should be a collection, in this case a list, whose elements are ultimately of type e. Any single object is such a collection, and its element type is itself; thus, the first instance declaration allows us to flatten anything into a singleton list. The second instance declaration says that if we can flatten an f into a list of es, then we can also flatten a list of fs into a list of es by flattening each f and sticking the resulting lists together. This recursive class definition defines the function recursively for the nested list types, giving you the ability to flatten a list of any nesting with the single function flatten: [1,2,3], [[4,5],[6]], [[[7,8],[9]],[[10]],[[11],[12]]], and so on.
However, because of the multiple instances and such, it does require a single type annotation: you will need to write, for instance, flatten [[True,False],[True]] :: [Bool]. If you have something that's type class-polymorphic within your lists, then things are a little stricter; you need to write flatten [[1],[2,3 :: Int]] :: [Int], and as far as I can tell, the resulting list cannot be polymorphic itself. (However, I could well be wrong about this last part, as I haven't tried everything by any means.) For a similar reason, this is too open—you could declare instance Flattenable [f] () where flatten = [()] if you wanted too. I tried to get things to work with type families/functional dependencies in order to remove some of these problems, but thanks to the recursive structure, couldn't get it to work (I had no e and a declaration along the lines of type Elem a = a and type Elem [f] = Elem f, but these conflicted since [f] matches a). If anyone knows how, I'd very much like to see it!
Again, sorry about the length—I tend to start blathering when I get tired. Still, I hope this is helpful!
You are confusing the interactive command :t in the interpreter with a built-in function. You cannot query the type at runtime.
Look at the example for that problem:
flatten (List [Elem 1, List [Elem 2, List [Elem 3, Elem 4], Elem 5]])
As you see, the problem wants you to create your own data structure for arbitrarily nested lists.
Normal haskell lists can not be arbitrarily nested. Every element of the list has to have the same type, statically known, which is why it makes no sense to check the type of the elements dynamically.
In general haskell does not allow you to create a list of different types and then check the type at runtime. You could use typeclasses to define different behaviors for flatten with different types of arguments, but that still wouldn't give you arbitrarily nested lists.

Resources