1

I have a simple nested data structure I can pattern match:

Prelude> data Token = Token String Int deriving ( Show )
Prelude> data Person = Person Token deriving ( Show )
Prelude> person = Person (Token "moish" 74)
Prelude> foo (Person (Token name _)) = "hello " ++ name

Is there an easy way to extract the name (moish) from p without pattern-match ?

foo :: Person -> String
foo p = -- ???
OrenIshShalom
  • 5,974
  • 9
  • 37
  • 87
  • 2
    Did you deliberately not use record syntax when defining `Token`? – leftaroundabout Sep 27 '22 at 17:52
  • @leftaroundabout yes, otherwise it's indeed easy – OrenIshShalom Sep 27 '22 at 17:52
  • 4
    Without pattern matching and record syntax there is no idiomatic way to extract data from data types. (There are hacks you can do with `unsafeCoerce` and friends, but I don't think that is what you want.) – Noughtmare Sep 27 '22 at 17:56
  • Not 100% a dupe of [Is it possible to write pattern-matched functions in pointfree form?](https://stackoverflow.com/q/46554677/625403), but closely related, and I expect you'd find the answer interesting. – amalloy Sep 27 '22 at 17:57
  • if you don't want to use record syntax to have getters generated for you, then you can of course simply write your own trivial getter function (using pattern matching). That allows you to avoid worrying pattern matches everywhere else. If you're not willing to write a getter, nor to use the language feature that will automatically generate a getter for you, what exactly do you want the language to do to help you? – Ben Sep 28 '22 at 00:45
  • @Ben I'm new to Haskell (as you might have noticed) so I wanted to make sure I'm not missing something. I thought there might be some auto-generated getter, or some other trick. The (equivalent of) `Person` + `Token` is legacy code I can not change - and it was not written with record syntax. – OrenIshShalom Sep 28 '22 at 03:48
  • 1
    @OrenIshShalom Oh yeah, it makes perfect sense to ask. But record syntax **is** the "trick" for auto-generated getters. If the legacy code didn't want record syntax, then you're out of luck. But you can still write them yourself easily enough (which also allows you the flexibility to e.g. get the name inside the `Token` inside the `Person` with a single getter, which is probably better than what you'd get out of record getters). – Ben Sep 28 '22 at 06:50
  • @OrenIshShalom "legacy code I cannot change". Do you mean the source is not available? Replacing `data Token = Token String Int deriving ( Show )` with `data Token = Token { tokenName :: String, tokenValue :: Int }` shouldn't break any existing code that already pattern-matches on `Token` values. (Choosing field names that don't conflict with existing code could be more difficult.) – chepner Sep 28 '22 at 12:41
  • @chepner It does change the `Show` instance though, and there's enough code it there that actually uses `show` for things like serialisation that I wouldn't want to bet it's safe to just do that in any old legacy project. – Ben Sep 29 '22 at 02:15

1 Answers1

9

Nope. Pattern match is the one and only way to consume data. Everything else is built on top of that.

Daniel Wagner
  • 145,880
  • 9
  • 220
  • 380