Search code examples
haskellclassy-prelude

Why does Element show up in a type error using Foldable (not MonoFoldable) in ClassyPrelude?


I have the following custom prelude:

{-# LANGUAGE DataKinds #-}
{-# LANGUAGE RankNTypes #-}


module Prelude (
  module ClassyPrelude
, module Numeric.Units.Dimensional.Prelude
, headMay
, sec
) where

import ClassyPrelude hiding
    ( (+), (-), (*), (/), (^), (**)
    , abs, signum, negate, recip, pi, exp, log, logBase, sqrt
    , sin, cos, tan, asin, acos, atan, atan2
    , sinh, cosh, tanh, asinh, acosh, atanh
    , sum, product, minimum, maximum
    ) -- Hide definitions overridden by 'Numeric.Dimensional'.

import Numeric.Units.Dimensional.Prelude hiding (
    (++)
  , all,and, any, break, concat, concatMap, drop, dropWhile, elem, filter, foldMap, foldr
  , getChar, getContents, getLine, head, init, interact, lookup, map, mapM_, notElem, null, or, print, putChar
  , putStr, putStrLn, readFile, replicate, sequence_, splitAt, undefined, writeFile
  , last, length, lines, reverse, second, span, tail, take, takeWhile, unlines, unwords
  , unzip, unzip3, words, zip, zip3, zipWith, zipWith3
  ) -- hide other conflicts specific to classy prelude

import qualified Numeric.Units.Dimensional.Prelude as NUDP

headMay :: Foldable f => f a -> Maybe a
headMay = foldr (const . Just) Nothing

sec :: Num a => Unit Metric DTime a
sec = NUDP.second

The relevant bit here is just (I think) Classy Prelude and the definition of headMay:

headMay :: Foldable f => f a -> Maybe a
headMay = foldr (const . Just) Nothing

The error I get when trying to compile this is:

/prelude/Prelude.hs:32:18: error:
    • Couldn't match type ‘a’ with ‘Element (f a)’
      ‘a’ is a rigid type variable bound by
        the type signature for:
          Prelude.headMay :: forall (f :: * -> *) a.
                             Foldable f =>
                             f a -> Maybe a
        at prelude/Prelude.hs:31:1-39
      Expected type: Element (f a) -> Maybe a -> Maybe a
        Actual type: a -> Maybe a -> Maybe a
    • In the first argument of ‘foldr’, namely ‘(const . Just)’
      In the expression: foldr (const . Just) Nothing
      In an equation for ‘Prelude.headMay’:
          Prelude.headMay = foldr (const . Just) Nothing
    • Relevant bindings include
        headMay :: f a -> Maybe a (bound at prelude/Prelude.hs:32:1)
   |
32 | headMay = foldr (const . Just) Nothing
   |                  ^^^^^^^^^^^^

Solution

  • classy-prelude exports a MonoFoldable version of foldr, through the reexport of Data.MonoTraversable.Unprefixed:

    https://hackage.haskell.org/package/mono-traversable-1.0.9.0/docs/Data-MonoTraversable-Unprefixed.html