I am reading the source code of reads
. reads
is defined as reads :: Read a => ReadS a
So it simply returns ReadS a
while a has to be a instance of Read
.
And ReadS a
is defined as type ReadS a = String -> [(a, String)]
, so the thing returned from reads
is only a function that take a string and return an array of tuple.
Then I wonder why just define reads
without ReadS a. Just like
reads :: Read a => (String -> [(a, String)])
in https://www.haskell.org/tutorial/goodies.html type [a] is defined as followed: [a] is the family of types consisting of, for every type a, the type of lists of a. Lists of integers (e.g. [1,2,3]), lists of characters (['a','b','c']), even lists of lists of integers, etc., are all members of this family.
In Haskell read function is used to deal with strings, if you want to parse any string to any particular type than we can use read function from the Haskell programming. In Haskell read function is the in built function, that means we do not require to include or install any dependency for it, we can use it directly.
Haskell has first-class functions : functions are values just like integers, lists, etc. They can be passed as arguments, assigned names, etc. … val is value of type Int , and half_of is a value of type Float -> Float .
The most basic way of defining a function in Haskell is to ``declare'' what it does. For example, we can write: double :: Int -> Int double n = 2*n. Here, the first line specifies the type of the function and the second line tells us how the output of double depends on its input.
A parser for things
is a function from strings
to lists of pairs
of things and strings!— Various sources
It aids in reasoning about programs to think about abstractions in terms of their intent, rather than their implementation. So yes, while type ReadS a = String -> [(a, String)]
, that’s secondary to the actual goal of parsing things, and of chaining ReadS
parsers together. As Rhymoid points out:
composeReads :: ReadS a -> ReadS b -> ReadS (a,b)
Conveys the intent of parser composition, and as a happy side effect is much more succinct, than the inlined equivalent:
composeReads
:: (String -> [(a, String)])
-> (String -> [(b, String)])
-> (String -> [((a, b), String)])
It’s a good and obvious thing to factor out this repetition, not least because it’s good to avoid repetition, but also to increase as much as possible the amount of useful semantic content per line. And if we want to change things about how these parsers are implemented, then encapsulating them behind this alias is a small step that may let us avoid massive changes to every single usage site.
You see this repeated in the various parser combinator libraries such as Parsec, Attoparsec, and uu-parsinglib. A Parser
is a Parser
is a Parser
, and the more like a black box these things are, the easier it is to play with their usage and implementation—separately.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With