Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 5838293
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 22, 20262026-05-22T11:27:09+00:00 2026-05-22T11:27:09+00:00

I’m new to Haskell and working my way through the Write Yourself a Scheme

  • 0

I’m new to Haskell and working my way through the Write Yourself a Scheme in 48 Hours project and I came upon an instance where I wanted to get the underlying type out of a data type and I’m not sure how to do it without writing conversions for each variant in the type.
For example, in the data type

data LispVal = Atom String
             | List [LispVal]
             | DottedList [LispVal] LispVal
             | Number Integer
             | String String
             | Bool Bool
             | Double Double

I want to write something like: (I know this doesn’t work)

extractLispVal :: LispVal -> a
extractLispVal (a val) = val

or even

extractLispVal :: LispVal -> a
extractLispVal (Double val) = val
extractLispVal (Bool val) = val

Is it possible to do this?
Basically I want to be able to cast back out of the LispVal if I need to use the basic type.

Thanks!
Simon

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-22T11:27:09+00:00Added an answer on May 22, 2026 at 11:27 am

    Unfortunately this sort of generic matching on constructors isn’t possible directly, but even if it was yours wouldn’t work–the extractLispVal function doesn’t have a well-defined type, because the type of the result depends on the value of the input. There are various kinds of advanced type-system nonsense that can do things sort of like this, but they’re not really something you’d want to use here anyway.

    In your case, if you’re only interested in extracting particular kinds of values, or if you can convert them to a single type, you can write a function like extractStringsAndAtoms :: LispVal -> Maybe String, for instance.

    The only way to return one of several possible types is by combining them into a data type and pattern matching on that–the generic form of this being Either a b, which is either a or b distinguished by constructors. You could create a data type that would permit all possible types to extract… and it would be pretty much the same as LispVal itself, so that’s not helpful.

    If you really want to work with various types outside of a LispVal you could also look at the Data.Data module, which provides some means for reflection on data types. I doubt that’s really what you want, though.


    EDIT: Just to expand on things a bit, here’s a few examples of extraction functions you can write:

    • Create single-constructor extraction functions, as in Don’s first example, that assume you already know which constructor was used:

      extractAtom :: LispVal -> String
      extractAtom (Atom a) = a
      

      This will produce runtime errors if applied to something other than the Atom constructor, so be cautious with that. In many cases, though, you know by virtue of being at some point in an algorithm what you’ve got, so this can be used safely. A simple example would be if you’ve got a list of LispVals that you’ve filtered every other constructor out of.

    • Create safe single-constructor extraction functions, which serve as both a “do I have this constructor?” predicate and an “if so, give me the contents” extractor:

      extractAtom :: LispVal -> Maybe String
      extractAtom (Atom a) = Just a
      extractAtom _ = Nothing
      

      Note that this is more flexible than the above, even if you’re confident of what constructor you have. For example, it makes defining these easy:

      isAtom :: LispVal -> Bool
      isAtom = isJust . extractAtom
      
      assumeAtom :: LispVal -> String
      assumeAtom x = case extractAtom x of 
                         Just a  -> a
                         Nothing -> error $ "assumeAtom applied to " ++ show x
      
    • Use record syntax when defining the type, as in Don’s second example. This is a bit of language magic, for the most part, defines a bunch of partial functions like the first extractAtom above and gives you a fancy syntax for constructing values. You can also reuse names if the result is the same type, e.g. for Atom and String.

      That said, the fancy syntax is more useful for records with many fields, not types with many single-field constructors, and the safe extraction functions above are generally better than ones that produce errors.

    • Getting more abstract, sometimes the most convenient way is actually to have a single, all-purpose deconstruction function:

      extractLispVal :: (String -> r) -> ([LispVal] -> r) -> ([LispVal] -> LispVal -> r) 
                     -> (Integer -> r) -> (String -> r) -> (Bool -> r) -> (Double -> r)
                     -> LispVal -> r
      extractLispVal f _ _ _ _ _ _ (Atom x) = f x
      extractLispVal _ f _ _ _ _ _ (List xs) = f xs
      ...
      

      Yeah, it looks horrendous, I know. An example of this (on a simpler data type) in the standard libraries are the functions maybe and either, which deconstruct the types of the same names. Essentially, this is a function that reifies the pattern matching and lets you work with that more directly. It may be ugly, but you only have to write it once, and it can be useful in some situations. For instance, here’s one thing you could do with the above function:

      exprToString :: ([String] -> String) -> ([String] -> String -> String) 
                   -> LispVal -> String
      exprToString f g = extractLispVal id (f . map recur) 
                                        (\xs x -> g (map recur xs) $ recur x)
                                        show show show show
        where recur = exprToString f g
      

      …i.e., A simple recursive pretty-printing function, parameterized by how to combine the elements of a list. You can also write isAtom and the like easily:

      isAtom = extractLispVal (const True) no (const no) no no no no
        where no = const False
      
    • On the other hand, sometimes what you want to do is match one or two constructors, with nested pattern matches, and a catch-all case for the constructors you don’t care about. This is exactly what pattern matching is best at, and all the above techniques would just make things far more complicated. So don’t tie yourself to just one approach!

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm new to using the Perl treebuilder module for HTML parsing and can't figure
I have a jquery bug and I've been looking for hours now, I can't
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have a string like this: La Torre Eiffel paragonata all’Everest What PHP function
I want use html5's new tag to play a wav file (currently only supported
I'm parsing an RSS feed that has an ’ in it. SimpleXML turns this
I'm working with an upstream system that sometimes sends me text destined for HTML/XML
That's pretty much it. I'm using Nokogiri to scrape a web page what has
I have just tried to save a simple *.rtf file with some websites and
I want to count how many characters a certain string has in PHP, but

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.