Композиция функций с аннотацией типа для значений по умолчанию

Допустим, у меня есть следующий тип:

data ImageSize = ImageSize {height :: Int, width :: Int}

Теперь я хочу преобразовать это в массив JSON (по устаревшим причинам поверхности API):

instance ToJSON ImageSize where
  toJSON ImageSize{..} = Array $ fromList $ Number <$> map (fromFloatDigits . fromIntegral) [height, width]

Это не скомпилируется с:

 error: [-Wtype-defaults, -Werror=type-defaults]
    • Defaulting the following constraints to type ‘Double’
        (RealFloat a0)
          arising from a use of ‘fromFloatDigits’
          at lib/Filler/Filler/Filler/Filler/Filler/ImageSize.hs:14:63-77
        (Num a0)
          arising from a use of ‘fromIntegral’
          at lib/Filler/Filler/Filler/Filler/Filler/ImageSize.hs:14:80-98
    • In the first argument of ‘map’, namely ‘fromFloatDigits’
      In the second argument of ‘(<$>)’, namely
        ‘map (fromFloatDigits . fromIntegral) [height, width]’
      In the second argument of ‘($)’, namely
        ‘Number
           <$> map (fromFloatDigits . fromIntegral) [height, width]’

Эта проблема (тривиально) решается:

toJSON ImageSize{..} = Array $ fromList $ Number <$> map (fromFloatDigits) [(fromIntegral height) :: Double, (fromIntegral width)]

Но это кажется очень многословным и уродливым. Есть ли способ прикрепить типографию к композиции? Что-то вроде (fromFloatDigits . :: Double . fromIntegral), но на самом деле функционально?


person Abraham P    schedule 15.05.2020    source источник
comment
Не могу проверить прямо сейчас, но исправляет ли это использование TypeApplications? Используйте fromIntegral @Int в исходной попытке.   -  person chepner    schedule 15.05.2020


Ответы (1)


Просто используйте fromIntegral напрямую, не нужно добавлять дополнительный промежуточный тип.

toJSON ImageSize{..} = Array $ fromList $ Number <$> map fromIntegral [height, width]

Но еще проще использовать toJSON...

toJSON ImageSize{..} = toJSON [height, width]
person Daniel Wagner    schedule 15.05.2020