I'm trying to convert several projects to classy-prelude
at the moment. While most behaviour seems quite straightforward to me, the (head . head)
gives mysterious errors on a simple 2D list.
Consider the following GHCi session:
Prelude> (head . head) [[1,2],[3,4]]
1
Let's try this with ghci -XNoImplicitPrelude
and classy-prelude
:
> import ClassyPrelude
ClassyPrelude> (head . head) [[1,2],[3,4]]
<interactive>:10:1:
Couldn't match type `MinLen (Succ nat1) mono1' with `[[t0]]'
Expected type: [[t0]] -> Element mono0
Actual type: MinLen (Succ nat1) mono1 -> Element mono0
The function `head . head' is applied to one argument,
but its type `MinLen (Succ nat1) mono1 -> Element mono0'
has only one
In the expression: (head . head) [[1, 2], [3, 4]]
In an equation for `it': it = (head . head) [[1, 2], [3, 4]]
I assume GHC simply can't resolve the types for multidimensional lists correctly. Is there any way I can help it without resorting to (Prelude.head . Prelude.head)
?
As already mentioned in the comments, classy prelude's head function only works on traversables which are guarranted to have at least one element by the type-system, so that it doesn't have to be partial. Because all your lists have at minimum one element, you can just use the non-empty list type:
head . head $ mlcons (mlcons 1 $ mlcons 2 $ toMinLenZero []) $ mlcons (mlcons 3 $ mlcons 4 $ toMinLenZero []) $ toMinLenZero [] :: Int
-- 1
(The functions starting with ml
are all from the MinLen module of mono-traversable
, which is reexported by classy-prelude
)
If you just want the behaviour of the Prelude.head
function, you can use unsafeHead again from the mono-traversable
package and exported by default:
unsafeHead . unsafeHead [[1,2],[3,4]]
-- 1
There is also headMay
in that module, which can be used if you like to handle failure differently and not crash the whole program.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With