Updating a single field in a record with Haskell @

时间:2017-04-10 00:38:22

标签: haskell

I need to update one field of a very large default record.

As the default may change I don't want to rebuild the entire record manually.

Now I have come across the following way of doing this, but I am not sure how it works:

unaggregate :: MyResult -> MyResult
unaggregate calc@MyResult{..} = calc{ the_defaults = the_override
                                         `mappend` the_defaults }
  where
    the_override = create ("aggregation" := False)

I have tried searching for 'Haskell @ operator' in Google but it does not return immediately useful information.

I saw somewhere calc@MyResult{..} does pattern matching on variables but I don't see what variable calc does for the MyResult record...

Also I have looked up mappend (and Monoids) and I am not sure how these work either...

Thank you for any help

1 个答案:

答案 0 :(得分:4)

The @ symbol is called an "as-pattern". In the example above, you can use calc to mean the whole record. Usually you'd use it like this: calc@(MyResult someResult) -- so you can have both the whole thing and the pieces that you're matching. You can do the same thing with lists (myList@(myHead:myTail)) or tuples (myTuple@(myFst, mySnd). It's pretty handy!

MyResult{..} uses RecordWildcards. Which is a neat extension! BUT RecordWildcards doesn't help you update just one field of a record.

You can do this instead: calc { theFieldYouWantToUpdate = somethingNew }.