Convert Maybe String to (Maybe?) Integer - haskell

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.

Related

What is the type keyword in Haskell

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'

Passing any type in function signature in Haskell

I want to pass a function a wildcard or any type or even a way to choose between either of multiple types rather than just restrict it to String, or Number, or Boolean, for example:
myFunction :: a -> String
or
myFunction :: _ -> String
or
myFunction :: (String || Number) -> String
Is that possible?
myFunction :: a -> String is technically possible, however it's profoundly useless – since this must be able to deal with an argument of any type, there's nothing you can actually do with the argument. (It's a bit like getting a can with a completely unspecified substance – you wouldn't eat it in case it's corrosive, you couldn't use it for cleaning purposes in case it's fat, paint or glue, you couldn't process it further... in case of an unrestricted Haskell type you couldn't even analyse it.)
If you narrow it down to types that support some kind of common operation, a polymorphic argument can make sense:
myFunction' :: Show a => a -> String
myFunction' x = "The value is " ++ show x
Your other approach, supporting only two very specific types, is also possible:
myFunction'' :: Either String Integer -> String
myFunction'' (Left s) = "Got a string: “" ++ s ++ "”"
myFunction'' (Right n) = "Got a number: " ++ show n
Note that these two approaches are quite different: Show a => a -> String can be used as String -> String or as Integer -> String, or in fact any other type which supports the show operation (including newly-defined types of your own), but you must decide at compile-time which type you want. At runtime, all arguments passed to this function must then have the same type.
Either String Integer -> String can accept a mixture of String- and Integer values at runtime, but is always restricted to only these two types.
Defining a function a -> String is easily possible, it just won't be able to do anything useful unless you also restrict a to some typeclass (like Show).
_ -> String is not valid syntax. If it were, I imagine it would do the same as a -> String, so you can just use that.
(String || Number) -> String is also not valid syntax, but Either String Number -> String is. You can also define your data type with constructors for the types you want to allow.
myFunction :: a -> String means that myFunction can take an argument of any type, but will always return a string. This is legal Haskell syntax.
With PartialTypeSignatures enabled, myFunction :: _ -> String is legal Haskell syntax, with _ acting as a "hole", or a way to get the compiler to tell you what type it inferred at that position:
Temp.hs:4:15: warning: [-Wpartial-type-signatures]
• Found type wildcard ‘_’ standing for ‘String’
• In the type signature: myFunction :: _ -> String
|
4 | myFunction :: _ -> String
| ^
If you enable TypeOperators, then you can define type (||) = Either, which make myFuncion :: (String || Number) -> String mean that myFuncion is a function that takes an argument of type Either String Number and returns a String:
type Number = Integer
type (||) = Either
myFuncion = (String || Number) -> String
myFuncion (Left string) = string
myFuncion (Right number) = show number

String replace using map compilation error

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

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.

Haskell Convert numbers in a string into a type

I have defined a type as:
type Register = Int
I'm also able to read in a list of numbers from a list of Strings using a function like:
readInt :: String -> Int
readInt s = read s :: Int
now, using readInt on a list like readInt "12 32 11" gives me [12, 32, 11] which is of type [Int].
My question is: instead of [Int], how can I get [Register].
I tried:
readRegister :: String -> Register
readRegister s = read s :: Register
but as I guessed, it doesn't seem to be valid syntax.
Your definition of Register is a type alias, i.e. it is interchangeable with its right hand side, i.e. here with Int.
But you state that readInt "12 32 11" would yield [12,32,11] :: [Int]. This is impossible given your type signature of readInt :: String -> Int. Perhaps you could show us a bit more of your code.
Register is just another name for the type Int, it is the same type. The syntax
readRegister :: String -> Register
readRegister s = read s :: Register
is valid (but the type annotation on the read result is unnecessary). If it doesn't work, your compiler/interpreter is broken. Whether the type is displayed as Int or Register, however, may be surprising. It's not easy to predict when a type synonym is expanded and when not.

Resources