Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell unsafeCoerce newtype to identical newtype

Imagine there is a newtype declaration:

newtype T = T Int

This declaration is in a module but not exported. I would like to pass a value of type T to a function. Now, I can declare my own version of T using the exact same definition. The compiler will of course complain if I pass (my.T 0) to a function expecting (hidden.T 0). I will use unsafeCoerce to coerce the former to the latter. It's mentioned here that usage is safe "between a newtype and the type that it wraps." I would like to just check if it's also safe in the case I described.

I know this is frowned upon and against all principles of good software practices, type theory, functional programming philosophy, ghc policies, common sense,..etc. Yet, I want to know if this will "normally" work.

like image 265
aelguindy Avatar asked Jan 27 '12 16:01

aelguindy


1 Answers

This might be safe with the current GHC implementation, but this is not the recommended way to solve your particular problem.

The pattern that is usually used instead is to have an internal module like this:

module Foo.Types (T(..)) where

newtype T = T Int

This module is declared as un-exported in your Cabal file. Then, in the module where you want to use the type in, you import the Types module, and use the constructor directly:

module Foo.Bla where

import Foo.Types (T(..))

f :: T -> Bla
f (T int) = makeBla int

Finally, you can export the opaque type however you want. For example:

module Foo (T) where

import Foo.Types (T(..))

makeT :: Int -> T
makeT = T

It is possible to use coercion instead, but it would be a bad idea to rely on it.

like image 165
dflemstr Avatar answered Nov 15 '22 05:11

dflemstr