0

How to construct a value by given constructor name and constructor arguments. For example, having the following data type

{-# LANGUAGE DeriveGeneric #-}

data Test = Foo | Bar Int | Baz String Int deriving (Generic, Show)

I would have such function

make "Foo" -- > Foo
make "Bar" 1 -- > Bar 1
make "Baz" "hi" 777 -- > Baz "hi" 777

The solution in this article is pretty close, but it works for data types only with single data constructor.

EDIT

So why do I want to do this? I have a BERT-encoded data that comes from the client. I can decode it to the Terms from the bert package. I want to have something like this

case x of
  Foo -> do something
  Bar x -> do something with x

and so on instead of

case x of
  TupleTerm y ->
    case y of
      [AtomTerm "foo"] -> do something
      [AtomTerm "bar", IntTerm x] -> do something with x

EDIT2

I concluded, that I was going in the wrong way.

6
  • 1
    Well the problem with this is: what would the signature of the make function be? String -> Test, String -> Int -> Test? String -> String -> Int -> Test? Commented Aug 16, 2018 at 17:54
  • 1
    well even if that was possible, then how would you process this? What would the type of make some_string be? Since it depends on the value of some_string, it has no specific value, hence type contracts could no longer get satisfied. Commented Aug 16, 2018 at 18:10
  • 1
    This seems like an XY problem. Why do you want to do this? Commented Aug 16, 2018 at 18:24
  • 1
    I have a BERT encoded data, that comes from the web browser, and I'm trying to turn it into the plain Haskell values. It is annoying to match BERT Terms every time. Commented Aug 16, 2018 at 18:30
  • 1
    Now I think there should be a better way for such transformations. I.e. transform :: (Generic t, FromBert (Rep t)) => Term -> Maybe t Commented Aug 16, 2018 at 18:44

1 Answer 1

1

"I have a BERT encoded data, that comes from the web browser"

There is not a reasonable way to solve the problem as you have posed it. However, if you are parsing data and you want to turn it into a Haskell data structure, the place to select the constructor is within the parser. Something like:

make :: Parser Test
make = do
  tag <- parse string
  case tag of
    "Foo" -> Foo
    "Bar" -> Bar <$> int
    "Baz" -> Baz <$> string <*> int

sting :: Parser String
int   :: Parser Int
Sign up to request clarification or add additional context in comments.

1 Comment

Yes, I agree. But I want to do this in a generic way.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.