Making a type polymorphic - haskell

So i'm defining a type which a list of tuples basically and I can't work out how to make it polymorphic.
so far i've got
module ListTup where
type ListTup = [(Char, String)]
and I was wondering if it was possible to make it so that the Char part could be anything e.i String, int what ever.
Is it possible?
I tried to use the Maybe Type but it throw a ton of errors my way

You can include type variables when defining type synonyms, like so:
type ListTup a = [(a, String)].

It depends on what you want to do. If you want different lists each of which will have the same type in the tuple's first element, you can parametrise the type constructor, like C.Quilley suggested above.
If you want each of your lists to be able to have different types, you can box all required types in an algebraic type (discriminated union):
data MyKey = MyCharKey Char | MyStringKey String | MyIntKey Int
type ListTup = [(MyKey, String)]
You cannot have "whatever", because the types need to be decidable at compilation time.

Related

What does a stand for in a data type declaration?

Normally when using type declarations we do:
function_name :: Type -> Type
However in an exercise I am trying to solve there is the following structure:
function_name :: Type a -> Type a
or explicitly as in the exercise
alphabet :: DFA a -> Alphabet a
alphabet = undefined
What does a stand for?
Short answer: it's a type variable.
At the computation level, the way we define functions is to use variables to refer to their arguments. Like this:
f x = x + 3
Here x is a variable, and its value will be chosen when the function is called. Haskell has a similar (but not identical...) mechanism in its type sublanguage. For example, you can write things like:
type F x = (x, Int, x)
type Endo a = a -> a -> a
Here again x is a variable in the first one (and a in the second), and its value will be chosen at use sites. One can also use this mechanism when defining new types. (The previous two examples just give new names to existing types, but the following does more.) One of the most basic nontrivial examples of this is the Maybe family of types:
data Maybe a = Nothing | Just a
The things on the right of the = are computation-level, so you can mostly ignore them for now, but on the left we are declaring a new family of types Maybe which accepts other types as an argument. For example, Maybe Int, Maybe (Bool, String), Maybe (Endo Char), and even passing in expressions that have variables like Maybe (x, Int, x) are all possible.
Syntactically, type constructors (things which are defined as part of the program text and that we expect the compiler to look up the definition for) start with an upper case letter and type variables (things which will be instantiated later and so don't currently have a concrete definition) start with lower case letters.
So, in the type signature you showed:
alphabet :: DFA a -> Alphabet a
I suspect there are actually two constructs new to you, not just one: first, the type variable a that you asked about, and second, the concept of type application, where we apply at the type level one "function-like" type to another. (Outside of this answer, people say "parameterized" instead of "function-like".)
...and, believe it or not, there is even a type system for types that makes sure you don't write things like these:
Int a -- Int is not parameterized, so shouldn't be applied to arguments
Int Char -- ditto
Maybe -> String -- Maybe is parameterized, so should be applied to
-- arguments, but isn't

Haskell - Bags - How can I use polymorphism in Haskell?

I have just started learning Haskell and still haven't grasped Functional Programming. I need to create a polymorphic datatype whose type I don't know until one of the functions I've written is run. The program seems to want me to build a list of tuples out of a list, e.g.:
['Car', 'Car', 'Motorcycle', 'Motorcycle', 'Motorcycle', 'Truck'] would be converted to [('Car', 2), ('Motorcycle', 3), ('Truck', 1)].
Within a same list of tuples (a bag), all elements will be of the same type, but different bags may contain other types. Right now, my datatype declaration (I'm not sure if it's called 'declaration' in FP) goes:
type Amount = Int
data Bag a = [(a, Amount)]
However, when I try to load the module, I get this error:
Cannot parse data constructor in a data/newtype declaration: [(a, Amount)]
If I change data to type in the declaration, I get this error message for all functions:
Expecting one more argument to ‘Bag’
Expected a type, but ‘Bag’ has kind ‘* -> *’
Is there something I'm not grasping about FP or is it a code error?, and more importantly, how can I declare this in a way that actually allows me to load the module into GHCi?
Defining a data type
This is not about functional programming itself. If you define a datatype (or newtype), in Haskell it needs a data constructor (for newtype there can only be one data constructor, and with one parameter). [(a, Amount)] is however not a good "name" for a data constructor (well you did not intend to use that as a data constructor anyway).
We can here write a data constructor like:
data Bag a = Bag [(a, Amount)]
and since here Bag contains (likely) one data constructor with one parameter, we can make it a newtype:
newtype Bag a = Bag [(a, Amount)]
The above however might not be necessary: you might want to declare a type alias with type:
type Bag a = [(a, Amount)]
in that case, you did not construct a new type, but you can write Bag a, and "behind the curtains", Haskell will replace this with [(a, Amount)].
Define functions with Bag
In case you now want to define a function that processes a Bag, you will need to specify the parameter a in the signature as well, for example:
count :: Eq a => [a] -> Bag a
count = -- ...
Now it is clear that we transform a list of as, in a Bag of as.

Can you mix record syntax with enumerations in Haskell data types?

I've written the following:
data Expression = Expression { lhs :: Int, rhs :: Expression } | Int
The problem is if I try to construct an Expression with just an int I get a partially applied function. What's the best way to fix this?
Things to know up front:
every data constructor in a Haskell data declaration has its own name
data constructors live in an entirely separate namespace from type names
As the comments note, you are defining both a type named Expression and a data constructor named Expression. Because Haskell has separate namespaces for types and data constructors, the compiler is fine with this.
Also, you are creating a second data constructor named Int (which likewise doesn't conflict with the existing type named Int). This is probably not what you want, and is confusing to boot!
When you try to construct a value such as myExpr = Expression x y, you are using the first data constructor, not the type name or the second data constructor. The Expression data constructor expects two arguments: first an Int, then an Expression. That is why, if you just provide the first argument, you will get a partially applied function.
A corrected, more idiomatic version of your example might be:
data Expression = Assignment { lhs :: Int, rhs :: Expression }
| Literal { value :: Int }
It is actually fairly common to see a data constructor with the same name as its type, if it is the only data constructor:
data Foo = Foo { unwrapFoo :: Int }
For the sake of completeness, the answer to your question is yes. The other answer provides an excellent explanation of what your current code does, but the short answer to your question is that
data Expression = Assignment { lhs :: Int, rhs :: Expression }
| Literal Int
is a completely valid type declaration. That being said, it's not tremendously idiomatic, so if you're going to use record syntax, you should probably use it for each data constructor of a given type.

haskell - Cannot parse data constructor in a data/newtype declaration: [Either Int Int]

I'm trying to declare a datatype that is a list of Either types.
data EitherInts = [Either Int Int]
But when I try to compile this type I get an error:
Cannot parse data constructor in a data/newtype declaration: [Either Int Int]
I have no idea why. What am I doing wrong?
data is for defining new algebraic data types, which must each have their own constructor(s). So you could write
data EitherInts = EitherInts [Either Int Int]
But you probably don't mean this: you want some kind of type synonym. There are two possibilities:
type EitherIntsType = [Either Int Int]
or
newtype EitherIntsNewtype = EitherInts [Either Int Int]
The first, using type, acts exactly like [Either Int Int]: a value such as [Left 2] is a valid value of the new EitherIntsType type. It's just a new, abbreviated name for that existing type, and can be used interchangeably with it. This approach is fine when you just want to be able to use a different name for an existing type: for clarity, or to give a shorter name to a much longer type.
The second, using newtype, is more heavy-weight. It acts more like data, with its own constructor. Values like [Left 2] are not valid values of the new EitherIntsNewtype type. Instead, you must write EitherintsNewtype [Left 2] to lift an existing list value, and you must pattern-match to extract values. This approach is better when you want the compiler's help making sure you don't mix up lifted and unlifted values, or when you want something like an existing type but with different typeclass instances (because you can give your newtype its own typeclass instances, which a type can't have).

Haskell typing for Int's and Double's

Just quick question about typing.
If I type into ghci :t [("a",3)] I get back [("a",3)] :: Num t => [([Char], t)]
Inside a file I have defined a type as:
type list = [(String, Int)]
How can I change the type to support both Ints and Doubles with the type I have defined, similar to what I wrote in ghci?
First, you have an error in your code. Data types must start with capital letters:
type List = [(String, Int)]
(Note that String is a type synonym for [Char], i.e. they are exactly the same type). We'll solve your problem in a roundabout way. Note that you can make the type completely general in the second slot of the tuple:
type List a = [(String,a)]
so that your type parameterizes over arbitrary types. If you need to specialize to numeric types in some function, then you can make that specialization for each function individually. For example:
foo :: Num a => List a
foo = [("Hello",1),("World",2)]
We could have included a constraint in the data type, like this:
data Num a => List a = List [(String,a)]
but you would still have to include the constraint Num a => ... in every function declaration, so you don't actually save any typing. For this reason, Haskell programmers generally follow the rule "Don't include type constraints in data declarations."

Resources