Why is a String in Haskell recognized as (wrong) type [Char]? - haskell

I have a function
mytest :: Int -> String
mytest = "Test"
ghci refuses to load the file:
Couldn't match expected type ‘Int -> String’
with actual type ‘[Char]’
In the expression: "Test"
In an equation for ‘mytest’: mytest = "Test"
Failed, modules loaded: none.
Everything works once I add a wildcard operator:
mytest :: Int -> String
mytest _ = "Test"
Does anyone know why Haskell interprets the first "Test" as [Char] and the second one as String?

String is just an alias for [Char]. It is defined like this:
type String = [Char]
A list of Char constitutes an String.
Your original function didn't work because the type checker is trying to match "Test" which is a String or [Char] data type with Int -> String type which results in a type error. You can make it work either by returning a function of Int -> String type:
mytest :: Int -> String
mytest = \x -> show x
which can be also written as:
mytest :: Int -> String
mytest x = show x
Or as you have done:
mytest :: Int -> String
mytest _ = "Test" -- Return "Test" no matter what the input is

Related

Convert Maybe String to (Maybe?) Integer

I would like to convert a Maybe String type to an Integer.
My actual code is:
let rule = getParamRule args -- this is a Maybe String type
let rule_int = read rule::Int -- I would like to convert to (Maybe) Integer
print rule
print rule_int
test.hs:26:23: error:
• Couldn't match type ‘Maybe String’ with ‘[Char]’
Expected type: String
Actual type: Maybe String
• In the first argument of ‘read’, namely ‘rule’
In the expression: read rule :: Maybe Int
In an equation for ‘rule_int’: rule_int = read rule :: Maybe Int
Use Text.Read.readMaybe
readMaybe :: Read a => String -> Maybe a
Parse a string using the Read instance. Succeeds if there is exactly
one valid result.
> readMaybe "123" :: Maybe Int
Just 123
> readMaybe "hello" :: Maybe Int
Nothing
Before using that, you need to import the module using
import Text.Read
at the beginning of your file (after the module ... line, if you have one).
Note that you can search hoogle by type. In this case, searching for String -> Maybe Int shows readMaybe as the 11th result. Could be better, but it is still shown in the first page.

How to create a newtype of parser?

newtype Parser a = PsrOf{
-- | Function from input string to:
--
-- * Nothing, if failure (syntax error);
-- * Just (unconsumed input, answer), if success.
dePsr :: String -> Maybe (String, a)}
I want to create a newtype of Parser to see how it looks like.
I tried
*ParserLib> PsrOf{"hello"}
But it comes up with an error
<interactive>:5:7: error: parse error on input ‘"’
You've already created the type. Now you want to create a value of that type. To do that, you need to call PsrOf with a value of type String -> Maybe (String, a). For example:
newtype Parser a = PsrOf { dePsr :: String -> Maybe (String, a) }
get3 :: String -> Maybe (String, Int)
get3 ('3':xs) = Just (xs, 3)
get3 _ = Nothing -- Any string, including the empty string, that doesn't start with '3'
get3P :: Parser Int
get3P = PsrOf get3
To actually use the parser, you need to extract the function before applying it to a string:
dePsr get3P "38" -- Just ("8", 3)
dePsr get3P "" -- Nothing
dePsr get3P "hello" -- Nothing
Record syntax here is just used to simplify the definition of the type, instead of writing
newtype Parser a = PsrOf (String -> Maybe (String, a))
dePsr :: Parser a -> String -> Maybe (String, a)
dPsr (PsrOf f) = f
The rest of the uses for record syntax (pattern matching or making slightly modified copies of a value) don't really apply usefully to types that wrap a single value.

How to get custom data type member?

This is what I have tried so far. I wanted to make a type Info with a String and two Ints. Now I want to access the String for a given instance of that type. I have read Accessing members of a custom data type in Haskell.
I did not expect this to work but couldn't search for what I'm looking for:
Prelude> data Info = Info String Int Int
Prelude> aylmao = Info "aylmao" 2 3
Prelude> aylmao . String
<interactive>:4:1: error:
• Couldn't match expected type ‘b0 -> c’ with actual type ‘Info’
• In the first argument of ‘(.)’, namely ‘aylmao’
In the expression: aylmao . String
In an equation for ‘it’: it = aylmao . String
• Relevant bindings include
it :: a -> c (bound at <interactive>:4:1)
<interactive>:4:10: error:
Data constructor not in scope: String :: a -> b0
Prelude>
I want to be able to access any anonymous member of my type, how can I do this?
How to get custom data type member?
data Info = Info String Int Int
As Willem Van Onsem said, you can write a function that does this:
infoString :: Info -> String
infoString (Info s _ _) = s
Or you can use record syntax to name your data type fields:
data Info = Info { infoString :: String
, infoInt1 :: Int
, infoInt2 :: Int
}
and use the automatically generated infoString :: Info -> String as a function.
Preferrably, come up with better names for those fields.

Returning different values of the same data type:

I'm writing a readValue function that can return any of Value's algebraic data types. The value constructors for Value aren't exported, so how can I return a Value?
Here's the documentation on Value.
Below is the function and the errors it produces:
readValue :: Label -> String -> Value
readValue label valueString =
case label of
"tags" -> (read valueString :: [String])
"text" -> (read valueString :: String)
src/Edit.hs:79:16:
Couldn't match type `Char' with `[Char]'
Expected type: [String]
Actual type: String
In the expression: (read valueString :: String)
In a case alternative: "text" -> (read valueString :: String)
In the expression:
case label of {
"tags" -> (read valueString :: [String])
"text" -> (read valueString :: String) }
You have:
readValue :: Label -> Value
You want:
readValue :: Label -> String -> Value
But:
(read valueString :: [String])
Has type [String] because that’s the type you gave it explicitly. Recall that :: has the lowest precedence. So the compiler is trying to unify String -> [String] with Value. That’s the source of your first error. The second error is caused by the :: String annotation on the second branch of the case, asking the compiler to try to unify String with [String], which too fails.
I suppose you want to wrap these values you’ve read into some of the Value constructors, which are indeed exported by Data.Bson, else you would be trying to return multiple different types from one function. But without knowing more about your problem, I can’t infer what you meant to do.
Here's the solution:
instance Val Value where
val = id
cast' = Just
readValue :: Label -> String -> Value
readValue label valueString =
case label of
"tags" -> val (read valueString :: [String])
"text" -> val (read valueString :: String)

Haskell abstract datatypes and retrieving characters/defining as strings

I had a datatype, example:
data MyData = Something1 String
and then I had a function
myFunction :: MyData -> String
myFunction x = x
within myFunction I want to refer to the characters ie ['S','o','m','e'......'1'] which are in my data type MyData. However, I get the following error:
Couldn't match expected type [Char]'
with actual typeMyData'
Expected type: String
Actual type: MyData
As far as I understand [Char] is the same as String, and I have declared 'Something1' as String, so it should work?
[Char] is the same as String, but neither is the same as MyData. To access the string stored within your data type, you'll need to use pattern matching:
myFunction :: MyData -> String
myFunction (Something1 xs) = xs
This is because the data keyword makes a completely new data type. If you only wanted an alias, you could also use the type keyword:
type MyData = String
myFunction :: MyData -> String
myFunction x = x
MyData is not the same as String. It is just very similar.
You can declare a type synonym like this:
type MyData = String
and then MyData and String are two names for the same type. In fact, String is already a type synonym of [Char]. In this case, myFunction is just the identity function id.
Or you can use pattern matching to extract the String from a MyData like this:
myFunction :: MyData -> String
myFunction (Something1 xs) = xs
Alternatively, you can use the record syntax to make the accessor automatically:
data MyData = Something1 { myFunction :: String}
(this is practically identical to declaring myFunction as above, except you can now construct MyDatas using the syntax Something1 { myFunction = x } as well as Something1 x)

Resources