Мне из wiki показалось, что это почти type
так, самое главние, ни в коем случае не сравнивай newtype с data, синтаксическая схожесть - ловушка, newtype это как type, только получается новый номинальный тип (а как следствие - инстансы оригинального типа забываются и можно определить свои)
newtype A = FromX X
fromX = FromX
fromA (FromX x) = x
A этот тот же X, но компилятор в компайлтайме будет их различать и не давать перепутать (в рантайме он это уже забудет). FromX в данном случае это не конструктор, а явный маркер для компилятора поменять нормальный тип (ничего не делая в рантайме при этом).
Фразы вида "newtype это как data только оптимизированный" может конечно формально и верны, но только буквой а не духом, и от этого заблуждения лучше избавиться сразу же, newtype это не оптимизированный data, newtype вообще не создает новых типов (в том смысле в котором data создает), просто дает новую номинальность другому типу.
Чтобы еще лучше понять, можно переписывать newtype в другой синтаксис
opaque type A = X
fromA :: A -> X
fromA = id
fromX :: X -> A
fromX = id
-- и в других модулях A и X уже абсолютно разные типы, и для конвертации можно делать только fromA/fromX
Имеет такой же синтаксис как data просто потому что разрабы языка решили не придумывать новый синтаксис и переиспользовать синтаксис конструкторов, что имхо не очень хорошая идея, из-за которой newtype сравнивают с data (а кроме синтаксиса ничего общего и нет).
То есть как теоретическое решение в вакууме это конечно прикольно что можно не делать новый синтаксис, а синтаксис конструтора (который можно использовать и для конструирования, и матчинга) использовать как метку для компиятора (которую как раз нужно использовать в обе стороны), но на практике вот приводит к вот таким заблуждениям что "newtype это как data, но с одним конструктором и оптимизированный"