Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unwrapping newtype should be easier than coercedTo. #484

Open
amano-kenji opened this issue Mar 14, 2023 · 5 comments
Open

Unwrapping newtype should be easier than coercedTo. #484

amano-kenji opened this issue Mar 14, 2023 · 5 comments

Comments

@amano-kenji
Copy link

amano-kenji commented Mar 14, 2023

A minimal example of unwrapping a newtype

{-# LANGUAGE TypeApplications #-}
import Optics.Core

newtype Index = Index Int deriving (Show, Eq)

ix :: Index
ix = Index 3

ix2 = ix & coercedTo @Int %~ (*2)

@Int bugs me. When I unwrap a newtype, I shouldn't have to specify the wrapped type.

coerced often fails to infer the right types without explicit type declarations.

@arybczak
Copy link
Collaborator

newtype N1 = N1 Int deriving newtype Num
newtype N2 = N2 N1 deriving newtype Num

n2 :: N2
n2 = N2 $ N1 3

hmm = n2 & coercedTo %~ (*2)

Now, does coercedTo coerce N2 to N1 or Int?

@amano-kenji
Copy link
Author

amano-kenji commented Mar 14, 2023

hmm = n2 & coercedTo %~ (*2)

<interactive>:9:12: error:
    • Couldn't match representation of type ‘Integer’
                               with that of ‘Int’
        arising from a use of ‘coercedTo’
    • In the first argument of ‘(%~)’, namely ‘coercedTo’
      In the second argument of ‘(&)’, namely ‘coercedTo %~ (* 2)’
      In the expression: n2 & coercedTo %~ (* 2)

I didn't really think about nested newtypes. But, there is Control.Lens.Wrapped which I used when I used lens.

@phadej
Copy link
Contributor

phadej commented Mar 14, 2023

That uses ExtendedDefaultRules enabled in ghci, (EDIT: Which defaults the type of 2 to be Integer). In source files the error will be different (and equally or more unhelpful).

@adamgundry
Copy link
Member

I don't think there's any fundamental reason why we couldn't port Control.Lens.Wrapped, it's just that nobody has felt the need to. Unwrapping a single layer of a newtype is a reasonable request, it just isn't what coerced provides.

@phadej
Copy link
Contributor

phadej commented Mar 28, 2023

I think it's not worthy copying Wrapped.

Firstly, it's not just newtype unwrapper, there is

instance Wrapped (Seq a) where
  type Unwrapped (Seq a) = [a]

for example.

Secondly, there is https://hackage.haskell.org/package/newtype and https://hackage.haskell.org/package/newtype-generics which kind of do similar thing, but interestingly there is no newtype-coerce building on top of Coercible.

I don't think that yet another take should be added to optics. So far we mostly successfully avoided redoing things (the Ix / At being the only exception can think of, but that has a reason - it's very optics specific take).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants