r/haskell • • 18h ago

[ANN] nonempty-vector-1.0

Thumbnail hackage.haskell.org
35 Upvotes

Hey all,

I'm happy to announce `nonempty-vector-1.0`, coauthored with u/CatboyKoz who contributed a huge amount of code for the unboxed API. I think that generally rounds out the set of features we wanted to get out of `nonempty-vector` and we've closed out every outstanding issue.

Thanks everyone who contributed!


r/haskell • • 4h ago

How are you meant to use DuplicateRecordFields with record update?

10 Upvotes

So, DuplicateRecordFields allows us to define multiple records with the same fields:

data X = X { id :: Int, ...}

data Y = Y { id :: Int, ...} 

But now, it's not actually possible to use these in a record update without tripping a deprecation warning:

-- Ambiguous record update with parent type constructor 'X'
setXId :: Int -> X -> X
setXId i x = x { id = i }

Best I can tell, there's no real way to avoid this... in this contrived example, I could of course just write something like

setXId :: Int -> X -> X
setXId i X{..} = X{id = i, ..}

But that's just... not using the record update syntax, and gets very unwieldy in places the record update syntax is actually very convenient. The only other option I'm aware is to use module-qualified field names, which then means I have to create a new file for every little datatype I want to introduce? Especially for things like database models, API specs or forms, this is kind of unwieldy.

Otherwise I could of course also just... assign different names to these fields, but that kind of defeats the point of having DuplicateRecordFields.

There's OverloadedRecordUpdate, which I guess "fixes" this, but requires RebindableSyntax (a whole other can of worms) and is still marked as experimental last I checked.

So, am I missing something here? I guess I could use optics/lens, but I extremely rarely have any need for any of the actually "interesting" use cases for these, and they're pretty heavy dependencies just for some basic mucking around with records. So far I've just resorted to `-Wno-ambiguous-fields` because it still works for now, but clearly that's not not the intended long-term strategy.

Full examples

Normal:

{-# LANGUAGE GHC2024, DuplicateRecordFields #-}

newtype X = X { id :: Int }
newtype Y = Y { id :: Int }

-- test.hs:7:18: warning: [GHC-02256] [-Wambiguous-fields]
--    Ambiguous record update with parent type constructor ‘X’.
--    This type-directed disambiguation mechanism will not be supported
--      by -XDuplicateRecordFields in future releases of GHC.
--    Consider disambiguating using module qualification instead.

setXId :: Int -> X -> X
setXId i x = x { id = i }

The version with OverloadedRecordDot (works I guess but I don't really want to turn on RebindableSyntax everywhere)

{-# LANGUAGE
  GHC2024
  , DuplicateRecordFields
  , OverloadedRecordUpdate
  , RebindableSyntax
  , AllowAmbiguousTypes
#-}

import GHC.TypeLits(KnownSymbol)
import Prelude(Int)

newtype X = X { id :: Int }
newtype Y = Y { id :: Int }

setXId :: Int -> X -> X
setXId i x = x { id = i }

getField :: forall f. KnownSymbol f => X -> Int
getField (X i) = i

setField :: forall f. KnownSymbol f => X -> Int -> X
setField _ = X

r/haskell • • 7h ago

Mutants at the MCG - 6:00 PM Thurs 12th of November

3 Upvotes

​Tristan Mc Leay - Mutation Testing With Sydtest

The Group

Melbourne Compose Group is the monthly in-person meetup for functional programmers in Melbourne, which this month, is on the second Thursday of the month.

​Our November meeting will be 6:00-8:00 pm Thurs 12th of November at our regular venue, Activity Room 2 at Kathleen Syme Center in Carlton. Arrive from 5:30 for chat and socialising, talks start at 6:30pm. Please RSVP via Luma.

The Talk: ​Tristan Mc Leay - Mutation Testing With Sydtest

​Now that use of AI code generation tools has become prevalent, we need a way
to keep our agents honest. Is our code well tested? Have we skipped tests?
Are the tests sensible or meaningless? All of these could have been problems
before AI, but they take on an increased significance when we can produce
bigger changes than we might be able to genuinely concentrate on.

Mutation testing is a way of checking our test quality as well as our test
coverage: instead of just asking whether a line ran during testing, it asks
whether changes to that line would have caused the tests to fail. In the case
of a typed functional language, that might be swapping an operator, dropping a
case, hard-coding a boolean instead of an if or a guard. If the tests continue
to pass with a change in place, then the test suite is usually insufficiently
sensitive to changes.

Sydtest includes a mutation testing framework for GHC, implemented as a GHC
plugin alongside driver code. It was designed precisely for this problem - as
our coding switches to AI, we need AI to look at our mutation test results to
know what to do next.

In this presentation, I will take a tour of Sydtest’s mutation testing and
apply it to a code base. This code base has poor test coverage and was originally hand written but nowadays is essentially agent-coded.

​As always, newcomers welcome.

​Hope to see you there
-Ben Hutchison & John Walker