Pattern matching against monadic result?

点点圈 提交于 2020-01-04 05:12:11

问题


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, Strings, 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

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!