I am new to Haskell, and trying to implement the code from here to replace strings using a map. I am getting an error message during compilation that says
* Expecting one more argument to `StringMap'
Expected a type, but `StringMap' has kind `* -> *'
* In the type signature:
stringMapReplace :: (Show stringMap) => StringMap -> String -> String
I have tried searching, but the only answer I can find for the error is that I'm not clarifying what type StringMap is. However, I thought that is what Show stringMap was doing.
import Data.Map
import Data.Strings
type StringMap stringMap = [(String, String)]
myStringMap =
[
("org1", "rep1"),
("org2", "rep2")
]
stringMapReplace :: (Show stringMap) => StringMap -> String -> String
stringMapReplace [] s = s
stringMapReplace (m:ms) s = strReplace ms (replace (fst m) (snd m) s)
main :: IO ()
main = do
putStrLn "Enter some text:"
putStrLn =<< stringMapReplace myStringMap <$> toUpper getLine
Note: strReplace comes from Data.Strings
I don't know if there is anything else wrong with the code, as the compiler is only giving the error above right now. If you notice anything else right off, please feel free to mention (or leave it for me to debug later as practice).
You defined the type synonym StringMap to take an (unused) type parameter stringMap. Type synonyms, as opposed to newtype, data, and GADT declarations, must always be fully applied. Thus every occurrence of StringMap must be have a parameter supplied, like forall a . StringMap a, StringMap Int, etc. In the signature of stringMapReplace, you do not give StringMap a parameter, hence the error.
Two options:
Change StringMap to type StringMap = [(String, String)], because it doesn't need a parameter.
Give StringMap a parameter in the signature of stringMapReplace. What parameter, you ask? Any one, because it is ignored. For example, the following should work:
stringMapReplace :: StringMap String -> String -> String
Related
Stumbled on the type keyword in Haskell:
type Item = String
but not sure what it does, how to use it or how it is different from data. The online google search has been of no help.
I tried implementing it in a code like this:
import System.IO
main = do
putStrLn "Hello, what's your name?"
type Item = String
let test :: Item
test = "chris"
putStrLn test
but I got an error
parse error on input ‘type’
Please in a lay man's term what is type and how can it be used and how is it different from data?
It is a type alias. It means that you can use Item in your code where you can use String instead.
A type alias is often used when you for example want to give a name to more complex types. For example:
import Data.Map(Map)
type Dictionary = Map String String
here you thus can use Dictionary instead of each time writing Map String String.
It is furthermore often used if you want to specify that you are working with Items, the alias is then used in the type signature and in the documentation, which is often better than writing String.
It is also used if you do not yet know what type you will use for a specific object. By using a type alias, you can the work with Item, and later if you change your made define a type for Item or make it an alias of another type. This makes it more convenient to change the types.
I tried implementing it in a code like this:
import System.IO
main = do
putStrLn "Hello, what's your name?"
type Item = String
let test :: Item
test = "chris"
putStrLn test
A type alias is defined at the top level, so not in a do block, that would make a type definition locally scoped. While, like #moonGoose says, there are some proposals to make type definitions more locally scoped, currently it is not the case.
You can define the type alias like:
import System.IO
type Item = String
main = do
putStrLn "Hello, what's your name?"
let test :: Item
test = "chris"
putStrLn test
type A = B
means exactly the same as
typedef B A
in C or C++, and it behaves basically the same as simply
a = b
except that A and B are type-level entities, not value-level ones. For example
Prelude> type A = Int
Prelude> :i A
type A = Int -- Defined at <interactive>:1:1
Prelude> a = 37
Prelude> a
37
Because now A = Int, I can then use the type identifier A exactly everywhere I could also use Int directly:
Prelude> 37 :: Int
37
Prelude> 37 :: A
37
and even
Prelude> (37 :: Int) :: A
37
Note that there is no type conversion going on here, like you might have in other languages. Int and A are simply different names for the same type, so annotating with both is merely a tautology.
Contrast this with data (or newtype), which define a new, separate type which just happens to contain the, well, data of the specified type.
Prelude> data A' = A' { getA :: Int }
Prelude> (37 :: Int) :: A'
<interactive>:12:2: error:
• Couldn't match expected type ‘A'’ with actual type ‘Int’
• In the expression: (37 :: Int) :: A'
In an equation for ‘it’: it = (37 :: Int) :: A'
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.
I look at this declaration:
newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
Here is what I understand:
1) Parser is declared as a type with a type parameter a
2) You can instantiate Parser by providing a parser function for example p = Parser (\s -> Nothing)
What I observed is that suddenly I have a function name parse defined and it is capable of running Parsers.
For example, I can run:
parse (Parser (\s -> Nothing)) "my input"
and get Nothing as output.
How was this parse function got defined with this specific signature? How does this function "know" to execute the Parser given to it? Hope that someone can clear my confusion.
Thanks!
When you write newtype Parser a = Parser { parse :: String -> Maybe (a,String) } you introduce three things:
A type named Parser.
A term level constructor of Parsers named Parser. The type of this function is
Parser :: (String -> Maybe (a, String)) -> Parser a
You give it a function and it wraps it inside a Parser
A function named parse to remove the Parser wrapper and get your function back. The type of this function is:
parse :: Parser a -> String -> Maybe (a, String)
Check yourself in ghci:
Prelude> newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
Prelude> :t Parser
Parser :: (String -> Maybe (a, String)) -> Parser a
Prelude> :t parse
parse :: Parser a -> String -> Maybe (a, String)
Prelude>
It's worth nothing that the term level constructor (Parser) and the function to remove the wrapper (parse) are both arbitrary names and don't need to match the type name. It's common for instance to write:
newtype Parser a = Parser { unParser :: String -> Maybe (a,String) }
this makes it clear unParse removes the wrapper around the parsing function. However, I recommend your type and constructor have the same name when using newtypes.
How does this function "know" to execute the Parser given to it
You are unwrapping the function using parse and then calling the unwrapped function with "myInput".
First, let’s have a look at a parser newtype without record syntax:
newtype Parser' a = Parser' (String -> Maybe (a,String))
It should be obvious what this type does: it stores a function String -> Maybe (a,String). To run this parser, we will need to make a new function:
runParser' :: Parser' a -> String -> Maybe (a,String)
runParser' (Parser' p) i = p i
And now we can run parsers like runParser' (Parser' $ \s -> Nothing) "my input".
But now note that, since Haskell functions are curried, we can simply remove the reference to the input i to get:
runParser'' :: Parser' a -> (String -> Maybe (a,String))
runParser'' (Parser' p) = p
This function is exactly equivalent to runParser', but you could think about it differently: instead of applying the parser function to the value explicitly, it simply takes a parser and fetches the parser function from it; however, thanks to currying, runParser'' can still be used with two arguments.
Now, let’s go back to back to your original type:
newtype Parser a = Parser { parse :: String -> Maybe (a,String) }
The only difference between your type and mine is that your type uses record syntax, although it may be a bit hard to recognise since a newtype can only have one field; this record syntax automatically defines a function parse :: Parser a -> (String -> Maybe (a,String)), which extracts the String -> Maybe (a,String) function from the Parser a. Hopefully the rest should be obvious: thanks to currying, parse can be used with two arguments rather than one, and this simply has the effect of running the function stored within the Parser a. In other words, your definition is exactly equivalent to the following code:
newtype Parser a = Parser (String -> Maybe (a,String))
parse :: Parser a -> (String -> Maybe (a,String))
parse (Parser p) = p
Here is the problem. It looks simple yet
main = do
s <- getContents
let list = map (read::Int) (words s)
print list
Couldn't match expected type `Int' with actual type `String -> a0'
Probable cause: `read' is applied to too few arguments
In the first argument of `map', namely `(read :: Int)'
In the expression: map (read :: Int) (words s)
The problem was that I thought :: is like casting and I have to put the return type. The solution was to add full wanted |function signature instread.
read is a function (of type Read a => String -> a), so it can't have type Int. You could do read :: String -> Int, or you could put a type signature on list rather than read, so you get:
let list :: [Int]
list = map read (words s)
I am new to Haskell, and I have a little question about function type declaration. Suppose there are bunch of integers, we need to sum it and print it out. I am aware this works:
main = do
a <- fmap (map read . words) getContents :: IO [Int]
print $ sum a
buta <- fmap (map (read :: Int) . words) getContentsfailed. Why it failed? We know getContents is IO String, then words is dealing with String and return [String] to map (read :: Int), I thought it may goes fine, because we declared it to read an Int, but it failed.
Is it impossible to use type declaration inside a line of code, or I use it the wrong way. Thanks.
The problem is that read doesn't have the type Int, it has the type String -> Int (for your purposes). The map function only accepts a function as its first argument, and you're trying to say that read has type Int, which would mean it's not a function. There's also no way you can coerce the type Read a => String -> a to Int, so it would error on both of these problems.