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
Related
I'm still a beginner when it comes to Haskell syntax and functional programming languages so when I look at the type declaration for Data.Function.on which is on :: (b -> b -> c) -> (a -> b) -> a -> a -> c, my interpretation is that it takes four parameters: (b -> b -> c), (a -> b), a, a, and returns c. However, when I look at the general use syntax for Data.Function.on which is (*) `on` f = \x y -> f x * f y, it is only taking two function parameters, not four, so how does the type signature relate to the usage syntax?
my interpretation is that it takes four parameters
All Haskell functions take one argument. Some of them just return other functions.
The best way to look at the signature for on is as a higher-order function: (b -> b -> c) -> (a -> b) -> (a -> a -> c). This says "if you give me a binary operator that takes bs and gives a c and a way to get bs from as, I will give you a binary operator that takes as and gives a c". You can see this in the definition:
(*) `on` f = \x y -> f x * f y
The Haskell arrow for function types hides a simple but clever idea. You have to think of -> as an operator, like + and -, but for types. It takes two types as arguments and gives you a new type consisting of a function. So in
Int -> String
You have the types Int and String, and you get a function from an Int to a String.
Just like any other operator, you need a rule for a chain of them. If you think of -, what does this mean?
10 - 6 - 4
Does it mean (10 - 6) - 4 = 0, or does it mean 10 - (6 - 4) = 8? The answer is the first one, which is why we say that - is "left associative".
The -> operator is right associative, so
foo :: Int -> String -> String
actually means
foo :: Int -> (String -> String)
Think about what this means. It means that foo doesn't take 2 arguments and return a result of type String, it actually takes 1 argument (the Int) and returns a new function that takes the second argument (the String) and returns the final String.
Function application works the same way, except that is left associative. So
foo 15 "wibble"
actually means
(foo 15) "wibble"
So foo is applied to 15 and returns a new function which is then applied to "wibble".
This leads to a neat trick: instead of having to provide all the parameters when you call a function (as you do in just about every other programming language), you can just provide the first one or the first few, and get back a new function that expects the rest of the parameters.
This is what is happening with on. I'll use a more concrete version where 'f' is replaced by 'length'.
(*) on length
you give on its first two parameters. The result is a new function that expects the other two. In types,
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c
In this case (*) has type Num n => n -> n -> n (I'm using different letters to make this less confusing), so that is matched with the type of the first argument to on, leading to the conclusion that if type b is substitued by n then type c must be as well, and and must also be a Num instance. Therefore length must return some numeric type. As it happens the type of length is [d] -> Int, and Int is an instance of Num, so that works out. So at the end of this you get:
(*) `on` length :: [d] -> [d] -> Int
As an intuitive aid, I read this as "if you give me a comparator of type b, and a way to extract values of type b from values of type a, I will give you a comparator of type a".
E.g. if a is some composite data type and b is some numerical attribute of these data values, you can express the idea of sorting these composite data types by using Data.Function.on.
Support I have a list of type [Char], and the values enclosed are values of a different type if I remove their quotations which describe them as characters. e.g. ['2','3','4'] represents a list of integers given we change their type.
I have a similar but more complicated requirement, I need to change a [Char] to [SomeType] where SomeType is some arbitrary type corresponding to the values without the character quotations.
Assuming you have some function foo :: Char -> SomeType, you just need to map this function over your list of Char.
bar :: [Char] -> [SomeType]
bar cs = map foo cs
I hope I get this correctly and there is a way (if the data-constructors are just one-letters too) - you use the auto-deriving for Read:
data X = A | B | Y
deriving (Show, Read)
parse :: String -> [X]
parse = map (read . return)
(the return will just wrap a single character back into a singleton-list making it a String)
example
λ> parse "BAY"
[B,A,Y]
I am working on a project in Haskell for the first time and I am working on translating over my ADT into the code properly, however when I am writing the explicit type definitions for my functions and I load my code in GHCi I get the following error:
Blockquote parse error on input ‘::’
The line in question is for a function called type which accepts a character and a tuple and returns a tuple as shown below:
type :: validChars -> tuple -> tuple
where validChars is the list of valid characters, the definitions for my lists are shown here if this helps:
tuple = (l, r, b, k)
l = [l | l <- validChars]
m = [m | m <- validChars]
b = [b | b <- validChars]
k = [k | k <- validChars]
validChars = [ chr c | c <-alphanumericChars , c >= 32, c <= 122]
alphanumericChars = [ a | a <- [0..255]]
I checked to make sure it wasn't validChars causing the error by replacing it with the Charstype as shown:
type :: Chars -> tuple -> tuple
But I still get the same error, I am a complete beginner at Haskell so I'm probably missing something important, but I am not sure what that would be exactly; I've looked at answers for similar questions I have been unsuccessful thus far. Any help with this would be appreciated.
type is a keyword in Haskell, so you can't use it as the name of your function.
Furthermore type names start with a capital letter in Haskell and anything starting with a lower case letter in a type is a type variable. So if you define myFunction :: validChars -> tuple -> tuple, that defines a function that takes two arguments of arbitrary types and produces a result of the same type as the second argument. It's the same as myFunction :: a -> b -> b.
If you write myFunction :: Chars -> tuple -> tuple, you get a function whose first argument needs to be of type Chars (which needs to exist) and the second argument is of an arbitrary type that is also the type of the result. Again it's the same as myFunction :: Chars -> a -> a.
Note that for this to work, you'll actually have to have defined a type named Chars somewhere. If you want to take a list of Chars, the type should be [Char] instead.
And if you want the second argument and result to actually be tuples (rather than just a type variable arbitrarily named tuple), you need to specify a tuple type like (a,b,c,d), which would accept arbitrary 4-tuples, or something specific like (Integer, String, String, String), which would accept 4-tuples containing an Integer and three Strings.
In Haskell, why does this compile:
splice :: String -> String -> String
splice a b = a ++ b
main = print (splice "hi" "ya")
but this does not:
splice :: (String a) => a -> a -> a
splice a b = a ++ b
main = print (splice "hi" "ya")
>> Type constructor `String' used as a class
I would have thought these were the same thing. Is there a way to use the second style, which avoids repeating the type name 3 times?
The => syntax in types is for typeclasses.
When you say f :: (Something a) => a, you aren't saying that a is a Something, you're saying that it is a type "in the group of" Something types.
For example, Num is a typeclass, which includes such types as Int and Float.
Still, there is no type Num, so I can't say
f :: Num -> Num
f x = x + 5
However, I could either say
f :: Int -> Int
f x = x + 5
or
f :: (Num a) => a -> a
f x = x + 5
Actually, it is possible:
Prelude> :set -XTypeFamilies
Prelude> let splice :: (a~String) => a->a->a; splice a b = a++b
Prelude> :t splice
splice :: String -> String -> String
This uses the equational constraint ~. But I'd avoid that, it's not really much shorter than simply writing String -> String -> String, rather harder to understand, and more difficult for the compiler to resolve.
Is there a way to use the second style, which avoids repeating the type name 3 times?
For simplifying type signatures, you may use type synonyms. For example you could write
type S = String
splice :: S -> S -> S
or something like
type BinOp a = a -> a -> a
splice :: BinOp String
however, for something as simple as String -> String -> String, I recommend just typing it out. Type synonyms should be used to make type signatures more readable, not less.
In this particular case, you could also generalize your type signature to
splice :: [a] -> [a] -> [a]
since it doesn't depend on the elements being characters at all.
Well... String is a type, and you were trying to use it as a class.
If you want an example of a polymorphic version of your splice function, try:
import Data.Monoid
splice :: Monoid a=> a -> a -> a
splice = mappend
EDIT: so the syntax here is that Uppercase words appearing left of => are type classes constraining variables that appear to the right of =>. All the Uppercase words to the right are names of types
You might find explanations in this Learn You a Haskell chapter handy.
I'm following this introduction to Haskell, and this particular place (user defined types 2.2) I'm finding particularly obscure. To the point, I don't even understand what part of it is code, and what part is the thoughts of the author. (What is Pt - it is never defined anywhere?). Needless to say, I can't execute / compile it.
As an example that would make it easier for me to understand, I wanted to define a type, which is a pair of an Integer and a String, or a String and an Integer, but nothing else.
The theoretical function that would use it would look like so:
combine :: StringIntPair -> String
combine a b = (show a) ++ b
combine a b = a ++ (show b)
If you need a working code, that does the same, here's CL code for doing it:
(defgeneric combine (a b)
(:documentation "Combines strings and integers"))
(defmethod combine ((a string) (b integer))
(concatenate 'string a (write-to-string b)))
(defmethod combine ((a integer) (b string))
(concatenate 'string (write-to-string a) b))
(combine 100 "500")
Here's one way to define the datatype:
data StringIntPair = StringInt String Int |
IntString Int String
deriving (Show, Eq, Ord)
Note that I've defined two constructors for type StringIntPair, and they are StringInt and IntString.
Now in the definition of combine:
combine :: StringIntPair -> String
combine (StringInt s i) = s ++ (show i)
combine (IntString i s) = (show i) ++ s
I'm using pattern matching to match the constructors and select the correct behavior.
Here are some examples of usage:
*Main> let y = StringInt "abc" 123
*Main> let z = IntString 789 "a string"
*Main> combine y
"abc123"
*Main> combine z
"789a string"
*Main> :t y
y :: StringIntPair
*Main> :t z
z :: StringIntPair
A few things to note about the examples:
StringIntPair is a type; doing :t <expression> in the interpreter shows the type of an expression
StringInt and IntString are constructors of the same type
the vertical bar (|) separates constructors
a well-written function should match each constructor of its argument's types; that's why I've written combine with two patterns, one for each constructor
data StringIntPair = StringInt String Int
| IntString Int String
combine :: StringIntPair -> String
combine (StringInt s i) = s ++ (show i)
combine (IntString i s) = (show i) ++ s
So it can be used like that:
> combine $ StringInt "asdf" 3
"asdf3"
> combine $ IntString 4 "fasdf"
"4fasdf"
Since Haskell is strongly typed, you always know what type a variable has. Additionally, you will never know more. For instance, consider the function length that calculates the length of a list. It has the type:
length :: [a] -> Int
That is, it takes a list of arbitrary a (although all elements have the same type) and returns and Int. The function may never look inside one of the lists node and inspect what is stored in there, since it hasn't and can't get any informations about what type that stuff stored has. This makes Haskell pretty efficient, since, as opposed to typical OOP languages such as Java, no type information has to be stored at runtime.
To make it possible to have different types of variables in one parameter, one can use an Algebraic Data Type (ADT). One, that stores either a String and an Int or an Int and a String can be defined as:
data StringIntPair = StringInt String Int
| IntString Int String
You can find out about which of the two is taken by pattern matching on the parameter. (Notice that you have only one, since both the string and the in are encapsulated in an ADT):
combine :: StringIntPair -> String
combine (StringInt str int) = str ++ show int
combine (IntString int str) = show int ++ str