问题
I am learning Haskell and want to use "readHex", which according to Hoogle has type:
readHex :: Num a => ReadS a
How do you "extract" a result from such a function? What's the most common way, pattern match against the right constructor ie, [(a,"")] ??
LiftM and lifting in general seems to make some sense, but I'm lost when it comes to "unwinding" the monadic stack.
回答1:
To answer the general question in general terms, the only way to extract values from a data constructor is pattern matching. Some data types come with functions that extract values for you, but those functions are themselves implemented with pattern matching, or call other functions that are, &c. Abstract data types like Data.Map.Map
or IO
, that want to hide their internal structure, still require pattern matching to work with; the difference is that they don't export their constructors from the module that defines them, so all you have to work with are other functions defined in the module and the operations they provide.
To answer the specific question, ReadS
is defined as such:
type ReadS a = String -> [(a, String)]
So it's just a type synonym. You don't need to extract anything from the ReadS
itself, it's just a shorthand or alias. The actual type is [(a, String)]
, which you can work with the same way you would anything else using lists, tuples, String
s, and so on.
Furthermore, ReadS
is not a Monad
. It's a type synonym for something that isn't a Monad
instance, and in fact can't be made into one directly (there's no way to write [(a, String)]
in the form required for an instance declaration).
回答2:
There's nothing monadic here. ReadS
is simply a type alias (link).
If you execute:
> readHex "41A"
Then you will get a singleton list of a tuple:
[(1050,"")]
There are numerous ways to extract the value 1050
. Some would use a case
statement. I would define an auxilary function using listToMaybe
:
readHexToVal :: Num a => String -> Maybe a
readHexToVal = listToMaybe . map fst . readHex
回答3:
The type ReadS a
is just a synonym for String -> [(a, String)]
. This is a function that accepts one input string and gives a list of matches - the first element is the resulting value and the second is the string that matched. In your case, there is most likely only one match, so I suggest you to use it like this:
case readHex str of
((num,""):_) -> ...
_ -> error ...
回答4:
You can pull out the result using let:
let ((d, _):_) = readHex "123ab"
来源:https://stackoverflow.com/questions/7181390/pattern-matching-against-monadic-result