I am tying to create a function where I enter an Algebraic data type list, and it should output an actual list.
For example, we have a list1 = P `Cons` (G `Cons` Empty)
The Output should be: [G,P]
I created the following Algebraic data types:
data Elements = G | S | P deriving (Eq, Show)
data List a = Empty | Cons Elements (List Elements)
and my current function is:
list:: Elements -> [List]
list Empty = []
list Cons a (List b) = [a] ++ list (List b)
I am having trouble solving this, and would appreciate if I get some help!
Thanks in advance!
Let's start with your data types:
From a technical standpoint, there's nothing wrong with
Elements, but it's a very poor choice of name. As others have noted, it's more usual to name the typeElement. The reason is that the English translation of your data type declaration is:when it would make more sense to say:
Also, when you start writing code with this type, it starts to get confusing. If you define a value of type
Elements:this represents a single element "platinum", and not a collection elements. This confusion might lead you to write a
listfunction with the wrong type signature because you think you're sayinglisttakes a bunch ofElementsbut the type signature actually says thatlisttakes only one element.For this reason, I'm going to do a search and replace of all your code, and the rest of my answer will talk about this version using "
Element" instead:Moving on, there is a problem with your
Listtype:You've defined a parameterized type
List a, but then you haven't used the parameterain its definition. In other cases where you've seen aList adefined it was because theaparameter was supposed to represent the type of list items, so the same list could be used to holdElements orInts or whatever. Since you want a special list data type that only holdsElements, you should writeListwithout a parameter (on both the left-hand side and the right-hand side of this declaration):Now, consider the type signature for
list:What
listis supposed to do is take a list of elements like:and produce a Haskell list as a result:
but this type signature says that
listis going to take a singleElementand produce a Haskell list whose items are of typeList(i.e., a customListofElements), in other words, it'll produce a list ofLists of elements. This certainly isn't right.In fact,
listshould take aListofElements and return a (Haskell) list ofElements, so the type signature should read:Note that if you loaded up just the type declarations into GHCi and checked the types of your example argument and result:
this would confirm that you want a function
List -> [Element].Now, your definition has two more errors:
Patterns like
Cons a (List b)need to be surrounded by parentheses to match a single argument, so this should read:There's still another problem here. The use of
Listdoesn't make sense here.Listis a type, and it belongs in type signatures, not in patterns or expressions, at least not like this. Haskell already knows that the second field ofConsis aList, so you don't need to tell it that. You just need to assign that field to a variable. If you eliminate theListfrom both sides:the final definition should type check:
If you want the result in reverse order, just flip the concatenation around:
The final code: