Is there a way to apply Maybe constructor to each field of record with generics?

前端 未结 2 1493
情深已故
情深已故 2021-01-19 10:33

I have two data types and the second one is the copy of first, but with Maybe on each field.

data A = {a :: Int, b :: String}
data B = {c :: Maybe Int, d ::          


        
2条回答
  •  夕颜
    夕颜 (楼主)
    2021-01-19 11:15

    How about:

    {-# LANGUAGE RankNTypes #-}
    
    data R f = R { a :: f Int, b :: f String, c :: f Char }
    
    newtype I a = I { unI :: a }
    
    fromMaybeI :: I a -> Maybe a -> I a
    fromMaybeI a Nothing = a
    fromMaybeI _ (Just a) = I a
    
    fromMaybeR :: R I -> R Maybe -> R I
    fromMaybeR ri rm =
      R (go a) (go b) (go c)
      where
        go :: (forall f. R f -> f a)  -> I a
        go x = fromMaybeI (x ri) (x rm)
    

    R Maybe is the record with Maybe values, R I is the record with concrete values.

    Using RankNTypes reduces the amount of boilerplate code in fromMaybeR.

    One downside is that you have use I and unI to construct and access the field values.

提交回复
热议问题