Understanding type - haskell

A few questions about the Haskell programming language:
What's the difference between these two code statements? I'm convinced they should be the same:
type T = [Char]
type CurrentValue = Char
My concern is that, in the second one, there are no brackets.
Anyway, they are actually declarations, aren't they?
What is Maybe String?
For instance: type P = (Char, Maybe String)
Is that a function which has two arguments?
What is Maybe Char?
For instance : type D = ((Maybe Char) , Char)
It's another function taking three arguments, right?

What's the difference between these two code statements?
type T = [Char]
type CurrentValue = Char
The first line declares a type alias T for [Char] which is a list of characters.
The second line declares another type alias CurrentValue for Char, a single character.
What is Maybe String?
It is an application of the type constructor Maybe to the type String (which is just an alias for [Char]). It is similar to how the brackets turn a type into a list of that type, except Maybe makes things optional.
For instance: type P = (Char, Maybe String)
Is that a function which has two arguments ?
No, that's a tuple type of two elements. The first element is a Char and the second is a Maybe String.
What is Maybe Char ?
For instance : type D = ((Maybe Char) , Char)
It's another function having three arguments. Am I right?
This is again a tuple type. The type of first element is Maybe Char and the second is Char. The inner parenthesis are redundant, so it's the same as type D = (Maybe Char, Char).

Re 1) T is a type synonym for a list of characters ([Char]), whereas CurrentValue is a type synonym for single characters (Char).
More info: http://learnyouahaskell.com/making-our-own-types-and-typeclasses#type-synonyms
Re 2) Maybe a can have values of Just a or Nothing. Imagine a computation that could go wrong: if it passes, it will return the result wrapped in a Just, if it fails it will return Nothing. In this specific case it would return a String (which btw is a type synonym for [Char] too) wrapped in a Just.
GOA> Just "foo"
Just "foo"
GOA> :type Just "foo"
Just "foo" :: Maybe [Char]
Re 3) See the answer for question number two, but for a single character instead of a list of characters.
GOA> :type Just 'f'
Just 'f' :: Maybe Char
More info: http://en.wikibooks.org/wiki/Haskell/Hierarchical_libraries/Maybe

1) With type you can declare a type synonym. So with type T = [Char], T is a type synonym for [Char] (list of Chars; square brackets denote a list in Haskell), meaning that T can be replaced with [Char] anywhere in the program (and vice versa). So don't be concerned about the lack of brackets.
2) Maybe String is a type a value of which may contain a string, or not. Maybe is used like pointers are often used in languages like C: if a function returns a Maybe String, it means that the function either succeeded and returns a string, or it failed and doesn't return a string. You can read more about the Maybe type here.
With type P = (Char, Maybe String) a type synonym P is declared as a synonym for a tuple. The first element of the tuple has the type Char and the second has the type Maybe String.
3) type D = ((Maybe Char), Char), or type D = (Maybe Char, Char) (the inner parentheses are unnecessary), declares a type synonym for a tuple with Maybe Char and Char as inner types.

The type Char indicates one single character while [Char] indicates a list of characters (i.e. a string).
type T = [Char]
is equivalent to
type T = String
If you have a type t then, intuitively, Maybe t indicates a type that has the same values
of t plus an extra undefined value (Nothing).
In its use this corresponds (very) roughly to the null value for Java objects.
So while String and Char represent the string and character types, Maybe String and Maybe Char represent a string resp. chararacter that can also be non-defined.

Related

Haskell: Parsing String to Custom Type

I have declared a type:
type Foo = (Char, Char, Char)
And want to be able to parse a 3 letter string "ABC" to produce an output Foo with each of ABC as the three attributes of the type.
My current attempt is;
parseFoo :: String → Maybe Foo
parseFoo str = f where
f (a, _, _) = str[0]
f (_, b, _) = str[1]
f (_, _, c) = str[2]
This is returning an error:
Illegal operator ‘→’ in type ‘String → Maybe Foo’
Use TypeOperators to allow operators in types
My question is:
How do I prevent this error on compilation?
Am I even on the right track?
If I understand it the correct way, you want to store the first three characters of a string into a type Foo (which is an alias for a 3-tuple that contains three Chars).
The signature seems correct (it is good practice to return a Maybe if something can go wrong, and here it is possible that the string contains less than three characters). A problem hwever is that you write an arrow character → whereas signatures in Haskell usse -> (two ASCII characters, a dash and a greater than symbol).
So we can define the signature as:
parseFoo :: String -> Maybe Foo
Now the second problem is that you here define a function f that maps Foos to Strings, so the reverse. You also make use of a syntax that is frequently used for indexing in languages of the C/C++/C#/Java programming language family, but indexing in Haskell is done with the (!!) operator, and since you define the function in reverse, it will not help.
A string is a list of Chars, so:
type String = [Char]
We can thus define two patterns:
a list with three (or more) characters; and
a list with less than three characters.
For the former, we return a 3-tuple with these characters (wrapped in a Just), for the latter we return Nothing:
parseFoo :: String -> Maybe Foo
parseFoo (a:b:c:_) = Just (a, b, c)
parseFoo _ = Nothing
Or if we do not want to parse strings with more than three characters successfully:
parseFoo :: String -> Maybe Foo
parseFoo [a, b, c] = Just (a, b, c)
parseFoo _ = Nothing

Pass no char to a function that is expecting it in Haskell

I am working with Haskell and I have defined the following type
--Build type Transition--
data Transition = Transition {
start_state :: Int,
symbol :: Char,
end_state :: Int
} deriving Show
and I would like to be able to define the following Transition
Transition 0 '' 1
which would be mean "a transition given by no symbol" (I need it to compute the epsilon closure of a NFA). How can I do this?
Thank you!
Well the idea of defining a type is that every value you pass to that field is a "member" of that type. Char only contains only characters (and the empty string is not a character) and undefined (but it is advisable not to use undefined here).
Usually in case you want to make values optional, you can use a Maybe a type instead, so:
data Transaction = Transaction {
start_state :: Int,
symbol :: Maybe Char,
end_state :: Int
} deriving Show
So now we can pass two kinds of values: Nothing which thus should be interpreted as "no character", or Just x, with x a character, and this thus acts as a character, so in your case, that would be:
Transaction 0 Nothing 1
Maybe is also an instance of Functor, Applicative and Monad, which should make working with Maybe types quite convenient (yes it can sometimes introduce some extra work, but by using fmap, etc. the amount of pattern matching shifting to Maybe Char should be rather low).
Note: like #amalloy says, an NFA (and DFA) has Transitions, not Transactions.

How to convert a nested list of Chars to a String Haskell

I have a simple question, although Lists of Chars seem equivalent to Strings, they are not functionally working the same. if I have a nested List of Chars, of type [[Char]] that I would like to convert to a [String], how would I go about doing this?
When I try to perform a function on the [[Char]] and treat it as though it is a string I get:
Couldn't match expected type `([String] -> (Int, Int, Board)) -> t'
with actual type `[[Char]]'
When I try to declare that type String = [[Char]] I get:
Ambiguous occurrence `String'
It could refer to either `Main.String', defined at Testing.hs:19:1
or `Prelude.String',
imported from `Prelude' at Testing.hs:16:1-14
(and originally defined in `GHC.Base')
Those two types are completely identical, because String is a type synonym for [Char]. The definition of String is
type String = [Char]
The type keyword means it's a type synonym. A type synonym is always interchangeable with the type it is defined to be.
You can see this in GHCi like this (note that Haskell does not allow casting):
ghci> let test :: [Char]; test = "abc"
ghci> test :: String
"abc"
ghci> :t (test :: [Char]) :: String
(test :: [Char]) :: String :: String
When I try to declare that type String = [[Char]] I get:
Ambiguous occurrence `String'
It could refer to either `Main.String', defined at Testing.hs:19:1
or `Prelude.String',
imported from `Prelude' at Testing.hs:16:1-14
(and originally defined in `GHC.Base')
You are getting this error because your definition of String conflicts with the one already defined in base and exported by the Prelude. Remove your definition and use the one that already exists instead.

Find and replace in Haskell

I want to input a list of 2 element lists of characters (just letters) where the first element is a letter in a String (the second argument for findAndReplace) and the second is what I want it changed to. Is there already a function in Haskell that does a similar thing? Because this would help greatly!
It sounds more like you might want to use a list of tuples instead of a list of lists for your first input, since you specify a fixed length. Tuples are fixed-length collections that can have mixed types, while lists are arbitrary-length collections of a single type:
myTuple = ('a', 'b') :: (Char, Char)
myTriple = ('a', 'b', 'c') :: (Char, Char, Char)
myList = ['a'..'z'] :: [Char]
Notice how I have to specify the type of each field of the tuples. Also, (Char, Char) is not the same type as (Char, Char, Char), they are not compatible.
So, with tuples, you can have your type signature for replace as:
replace :: [(Char, Char)] -> String -> String
And now this specifies with the type signature that it has to be a list of pairs of characters to find and replace, you won't have to deal with bad input, like if someone only gave a character to search for but not one to replace it with.
We now are passing in what is commonly referred to as an association list, and Haskell even has some built in functions for dealing with them in Data.List and Data.Map. However, for this exercise I don't think we'll need it.
Right now you're wanting to solve this problem using a list of pairs, but it'd be easier if we solved it using just one pair:
replace1 :: (Char, Char) -> String -> String
replace1 (findChr, replaceChr) text = ?
Now, you want to check each character of text and if it's equal to findChr, you want to replace it with replaceChr, otherwise leave it alone.
replace1 (findChr, replaceChr) text = map (\c -> ...) text
I'll let you fill in the details (hint: if-then-else).
Then, you can use this to build your replace function using the simpler replace1 function. This should get you started, and if you still can't figure it out after a day or two, comment below and I'll give you another hint.

Haskell filter function on strings

Is there a way to use the filter function on Strings, this way:
filter (=="!") "!!some!!_!!string!!"
should output "some_string" (case above). Right now all i get is a type error:
Couldn't match expected type `[Char]' against inferred type `Char'
If i change the second filter argument type to ["!!some!!_!!string!!"], the type error disappears, yet only an empty list is outputted. (Not exactly what i want)
I thought that strings were lists but obviously "!!some!!_!!string!!" isn't regarded as a list but as a char.
Any hints someone ?
Prelude> filter (/='!') "!!some!!_!!string!!"
"some_string"
The type of filter is (a -> Bool) -> [a] -> [a]. Since the 2nd argument is a String = [Char], meaning [a] = String = [Char], we infer that a must be a Char. The function therefore must take a Char as input. Therefore, you need to use '!', not "!".

Resources