The easiest answer is adding a field accessor:
type Foo :: Type
newtype Foo = Foo { getFoo :: [Int] }
bar :: [Int]
bar = toList $ getFoo $ Foo [1,2,3]
which works even if you parameterise Foo by the Foldable structure:
-- >> toList $ getFoo $ Foo [1,2,3]
-- [1,2,3]
-- >> toList $ getFoo $ Foo Nothing
-- []
type Foo :: (Type -> Type) -> Type
newtype Foo f = Foo { getFoo :: f Int }
If you do want guided coerce you can imagine a type family that resolves the underlying type. This is a standalone type family, unlike the associated Wrapped from the lens answer. I personally think this type family ought to be included in the standard library with instances magically generated by GHC.
type Underlying :: Type -> Type
type family Underlying a
type instance Underlying Foo = [Int]
type instance Underlying Any = Bool
type instance Underlying All = Bool
-- ..
underlying :: Coercible a (Underlying a) => a -> Underlying a
underlying = coerce
bar :: [Int]
bar = toList $ underlying $ Foo [1,2,3]
We don't need to define individual underlying unwrappings, all the definitions are coerce. You can now replace coerce with underlying which gives the compiler some guidance and it replaces getFoo; even in the parameterised case:
type instance Underlying (Foo f) = f Int
-- >> toList $ underlying $ Foo [1,2,3]
-- [1,2,3]
-- >> toList $ underlying $ Foo Nothing
-- []
Without the type family to tell what the target type is coerce is too general. There are arbitrarily many types coercible to/from Foo:
coerce
:: Foo -> [Int]
:: Foo -> Identity [Int]
:: Foo -> Identity (Sum (Product (Alt Identity (Ap [] Int))))
:: ..
I consider raw coerce appearing in code to be an anti-pattern because of this inference problem, and try to replace it with other abstractions like GeneralizedNewtypeDeriving or DerivingVia when I can.
That being said you are able to hold GHC's hand with TypeApplications where you explicitly specify the return type
>> toList $ coerce @_ @[Int] $ Foo [1,2,3]
[1,2,3]
>> toList $ coerce @_ @(Maybe Int) $ Foo Nothing
[]
or specify the input type of toList
>> toList @[] @Int $ coerce $ Foo [1,2,3]
[1,2,3]
>> toList @Maybe @Int $ coerce $ Foo Nothing
[]