3

In Haskell, if I specify field names for a type with a single constructor, the compiler should generate appropriate functions MyType -> fieldType. This breaks down if MyType has multiple constructors with different arities or types however. I want to know if there is some way I can tell the compiler to give these functions the signature MyType -> Maybe fieldType. i.e. instead of:

data MyType = Empty | Record { st :: String, ui :: Word }
-- where
-- st Empty == undefined
-- ui Empty == undefined

-- I have
data MyType = Empty | Record { st :: String, ui :: Word }
-- where
-- st :: MyType -> Maybe String
-- st Empty = Nothing
-- st (Record s _) = Just s
-- 
-- ui Empty = Nothing
-- ui (Record _ n) = n

I want to avoid the default behaviour of having expressions like st Empty returning undefined, because if st Empty returns Nothing, I can use pattern matching to decide on what to do next, rather than having to catch the exception further up the callstack in impure code. I realise this is not part of Haskell by default, so I wonder if there is a compiler extension that allows this? Alternately, could I implement something like this myself using templating?

myc3lium
  • 31
  • 5
  • 4
    You should never use record syntax with sum types, it is really a bad practice. If you want accessors and modifiers like the ones you are asking you need to write them yourself with some pattern matching. That being said, since it is pretty straightforward boiler plate I am sure you can write some template Haskell for it. I wouldn't be surprised if someone already did. – lehins Nov 28 '19 at 16:18

1 Answers1

3

No, there's no way to do this with record selectors. To understand why, remember that they can be used for record updates, rather than just as a function. If x = Empty, then there's still nothing reasonable that x { st = "foo" } could be. If you don't care about the functions actually being records, then you could use Template Haskell to generate just the functions you want, though.