Can I use type declaration inside Haskell code - haskell

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.

Related

Haskell: Show instance of IOArray

I'm learning Haskell and trying to use mutable arrays (in particular IOArray). I wrote a pretty printer that has the following type:
disp :: Show a => IOArray Int a -> IO String
I didn't manage to get rid of the IO part because of a subcall to
getBounds :: Ix i => a i e -> m (i, i)
Now I'm trying to use disp to define a Show instance for my IOArray type but the IO gets in the way.
Is it possible to create a Show instance for IOArray ?
An IOArray is not really an array. It's just a reference to an array. Absolutely everything interesting you can do with an IOArray produces an action in IO. Why is that? Suppose you could index into an IOArray in pure code:
(!) :: IOArray Int a -> a
Consider the following:
f :: IO (Char, Char)
f = do
ar <- newArray (0 :: Int, 10 :: Int) 'a'
let x = ar ! 3
writeArray ar 3 'b'
let y = ar ! 3
return (x, y)
What should f produce? One answer might be that it should produce ('a', 'b'), because the third element of ar started out as 'a' and then was changed to 'b'. But that's deeply troubling! How can ar ! 3 have one value at one time and another later? That violates the fundamental idea of referential transparency that purely functional languages are built on. So you just can't do that.
AFAIK in Haskell getting rid of Monads is neither possible nor correct. Some monads (like Maybe and Either) has special methods to unwrap their values, but (over)using them is discouraged. If you have any Haskell type that is wrapped within a Monad context, you must use it and work with it without unwrapping and releasing. For your case, any type within an IO monad, can not be converted (using any type of function like Show) to any type without IO Monad. One solution for your case is using Haskell's rich treasure of Monad functions and operators to convert inner type (e.g. Int) to Char, and after that you have a IO String instead of IOArray, which in turn you can print out.

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

Getting Result of IO Monad in ghci

Given:
Prelude> let x = return 100 :: IO Int
Trying to evaluate x returns its wrapped value.
Prelude> x
100
But, I can't get its value via show.
Prelude> show x
<interactive>:4:1:
No instance for (Show (IO Int)) arising from a use of ‘show’
In the expression: show x
In an equation for ‘it’: it = show x
What's going on when I type x in ghci?
If you enter an expression of type IO t into GHCi, it unwraps it and prints the resulting value. That is if you enter ioExp, GHCi executes val <- ioExp; print val (whereas if you enter a non-IO expression exp, GHCi executes print exp).
You can't show an IO Int action. The action may require to perform side effects to produce the Int, such as asking the user for such number. Instead, the type of show promises to return a String, i.e. a plain, pure string without any side effect.
You can define your own effectful variant of show, if you want:
showIO :: Show a => IO a -> IO String
showIO = fmap show
Note how the result above is not a plain string, but is wrapped inside the IO monad, as it should be.

How to explicitly instantiate/specialise a polymorphic Haskell function?

I was wondering whether it is possible to explicitly instantiate/specialise a polymorphic function in Haskell? What I mean is, imagine I've a function like the following:
parseFile :: FromJSON a => FilePath -> IO Either String a
The structure into which it attempts to parse the file's contents will depend on the type of a. Now, I know it's possible to specify a by annotation:
parseFile myPath :: IO Either String MyType
What I was wondering was whether it's possible to specialise parseFile more explicitly, for instance with something like (specialise parseFile MyType) to turn it into parseFile :: FilePath -> IO Either String MyType
The reason I ask is that the method of annotation can become clumsy with larger functions. For instance, imagine parseFile gets called by foo which gets called by bar, and bar's return value has a complex type like
:: FromJSON a => IO (([Int],String), (Int, String, Int), a, (Double, [String]))
This means that if I want to call bar with a as MyType, I have to annotate the call with
:: IO (([Int],String), (Int, String, Int), MyType, (Double, [String]))
If I want to call bar multiple times to process different types, I end up writing this annotation multiple times, which seems like unnecessary duplication.
res1 <- bar inputA :: IO (([Int],String), (Int, String, Int), MyType, (Double, [String]))
res2 <- bar inputB :: IO (([Int],String), (Int, String, Int), OtherType, (Double, [String]))
res3 <- bar inputC :: IO (([Int],String), (Int, String, Int), YetAnotherType, (Double, [String]))
Is there a way to avoid this? I'm aware it would be possible to bind the result of bar inputA and use it in a function expecting a MyType, allowing the type engine to infer that the a in question was a MyType without requiring explicit annotation. This seems to sacrifice type safety however, as if I accidentally used the result of the above bar inputB (an OtherType) in a function that expects a MyType, for instance, the type system wouldn't complain, instead the program would fail at runtime when attempting to parse inputB into a MyType, as inputB contains an OtherType, not a MyType.
First, a small correction, the type should be
parseFile :: FromJSON a => FilePath -> IO (Either String a)
The parenthesis are important and necessary
There are a couple ways around this. For example, if you had a function
useMyType :: MyType -> IO ()
useMyType = undefined
Then you used parseFile as
main = do
result <- parseFile "data.json"
case result of
Left err -> putStrLn err
Right mt -> useMyType mt
No extra type annotations are required, GHC can infer the type of mt by its use with useMyType.
Another way is to simply assign it to a concretely typed name:
parseMyTypeFromFile :: FilePath -> IO (Either String MyType)
parseMyTypeFromFile = parseFile
main = do
result <- parseMyTypeFromFile "data.json"
case result of
Left err -> putStrLn err
Right mt -> useMyType mt
And where ever you use parseMyTypeFromFile no explicit annotation is necessary. This is the same as a common practice for specifying the type of read:
readInt :: String -> Int
readInt = read
For solving the bar problem, if you have a type that complex I would at least suggest creating an alias for it, if not its own data type entirely, possibly with record fields and whatnot. Something similar to
data BarType a = (([Int], String), (Int, String, Int), a, (Double, [String]))
Then you can write bar as
bar :: FromJSON a => InputType -> IO (BarType a)
bar input = implementation details
which makes bar nicer to read too. Then you can just do
res1 <- bar inputA :: IO (BarType MyType)
res2 <- bar inputB :: IO (BarType OtherType)
res3 <- bar inputC :: IO (BarType YetAnotherType)
I would consider this perfectly clear and idiomatic Haskell, personally. Not only is it immediately readable and clear what you're doing, but by having a name to refer to the complex type, you minimize the chance of typos, take advantage of IDE autocompletion, and can put documentation on the type itself to let others (and your future self) know what all those fields mean.
You can't make a polymorphic function provided elsewhere and given an explicit annotation into a more restricted version with the same name. But you can do something like:
parseFileOfMyType :: FilePath -> IO Either String MyType
parseFileOfMyType = parseFile
A surprising number of useful functions in various libraries are similar type-specific aliases of unassuming functions like id. Anyway, you should be able to make type-constrained versions of those examples using this technique.
Another solution to the verbosity problem would be to create type aliases:
type MyInputParse a = IO (([Int],String), (Int, String, Int), a, (Double, [String]))
res1 <- bar inputA :: MyInputParse MyType
res2 <- bar inputB :: MyInputParse OtherType
res3 <- bar inputC :: MyInputParse YetAnotherType
In the not-too-distant future, GHC will possibly be getting a mechanism to provide partial type signatures, which will let you leave some sort of hole in the type signature that inference will fill in while you make the part you're interested in specific. But it's not there yet.

How to convert IO Int to String in Haskell?

I'm learning to use input and output in Haskell. I'm trying to generate a random number and output it to another file. The problem is that the random number seems to be returning an IO Int, something that I can't convert to a String using show.
Could someone give me a pointer here?
It's helpful if you show us the code you've written that isn't working.
Anyway, you are in a do block and have written something like this, yes?
main = do
...
writeFile "some-file.txt" (show generateRandomNumberSomehow)
...
You should instead do something like this:
main = do
...
randomNumber <- generateRandomNumberSomehow
writeFile "some-file.txt" (show randomNumber)
...
The <- operator binds the result of the IO Int value on the right to the Int-valued variable on the left. (Yes, you can also use this to bind the result of an IO String value to a String-valued variable, etc.)
This syntax is only valid inside a do block. It's important to note that the do block will itself result in an IO value --- you can't launder away the IO-ness.
dave4420's answer is what you want here. It uses the fact that IO is a Monad; that's why you can use the do notation.
However, I think it's worth mentioning that the concept of "applying a function to a value that's not 'open', but inside some wrapper" is actually more general than IO and more general than monads. It's what we have the Functor class for.
For any functor f (this could, for instance, be Maybe or [] or IO), when you have some value
wrapped :: f t (for instance wrapped :: Maybe Int), you can use fmap to apply a function
t -> t' to it (like show :: Int -> String) and get a
wrappedApplied :: f t' (like wrappedApplied :: Maybe String).
In your example, it would be
genRandomNumAsString :: IO String
genRandomNumAsString = fmap show genRandomNumPlain

Resources