2015-08-16 3 views
6

Вот конкретный случай общего вопроса я действительно прошу: Предположу, что я нахожусь в исполнении критической секции коды, и я получил значение,Haskell/GHC: Непонятно деконструкция конструктора?

x :: Maybe Int 

Я знаю, что это Just Int и не Nothing , но из-за кода из моего контроля, я не могу организовать получение фактического Int напрямую. Я хочу сделать

case x of 
    Just i -> whatever i 

, но я не хочу, чтобы GHC вставлял любые проверки или обработку ошибок или прыжки или что-то еще; просто интерпретируйте биты так, как будто они имеют форму Just i и позвольте мне разобраться с последствиями.

Возможно ли это? (Да, я знаю, это то, что не следует делать регулярно.)

+5

Возможно, сыграть некоторые уродливые трюки с 'unsafeCoerce' и при большом предположении о том, как GHC точно реализует свое время выполнения, вы можете достичь этого. Но...Я действительно сомневаюсь, что эта проверка - большая проблема: есть ли у вас какие-либо доказательства? Как говорит Кнут, преждевременная оптимизация - это корень всего зла. И не используйте «небезопасные» вещи, если вы действительно не можете обойтись без них. – chi

+0

Нет, у меня нет никаких доказательств, и я сделаю некоторый бенчмаркинг, прежде чем что-либо реализовать. –

+5

Вы посмотрели на скомпилированное ядро, которое генерирует ваша программа? В зависимости от того, почему «возможно» участвует в первую очередь, возможно *, что GHC, возможно, уже удалил его для вас ... – MathematicalOrchid

ответ

1

Иногда вы можете помочь GHC выяснить, что совпадение шаблона GADT является общим, добавляя некоторые подписи к шаблону. Я не совсем уверен, почему это иногда помогает, но может. Если вы действительно хотите небезопасно, способ сделать это - сделать более информативный GADT, чем тот, с которым вы работаете, и небезопасное принуждение к нему. Что-то вроде этого:

data Shmaybe :: Bool -> * -> * where 
    Noway :: Shmaybe r a 
    Shucks :: a -> Shmaybe True a 

fromShucks :: ShMaybe True a -> a 
fromShucks (Shucks a) = a 

unsafeFromJust :: forall a . Maybe a -> a 
unsafeFromJust m = fromShucks (unsafeCoerce m :: Shmaybe True a) 

Важно, чтобы конструкторы соответствовали типам и порядку аргументов. Очевидно, это все абсурдно небезопасно и не имеет никаких гарантий. Могут произойти ошибки сегментации.

1

Рассмотрим с помощью YOLOhttps://gist.github.com/nkpart/8922083d3c18a8f777b8 класса типов

instance Yolo Maybe where 
    yolo (Just x) = x 

N.B: Это была шутка. Используйте fromJust.

+0

'fromJust' включает в себя проверку на' Nothing', чего я хотел избежать. –

+1

Тогда, возможно, используйте 'Yolo' – Arnon

1

Мне известно о нескольких возможностях, но все неявно включают код для ошибок бросания в случае Nothing.

неопровержимые узор:

λ> let Just a = Just "hi" 
λ> a 
"hi" 
λ> let Just a = Nothing 
λ> a 
*** Exception: <interactive>:4:5-20: Irrefutable pattern failed for pattern Data.Maybe.Just a 

Non-exhastive модели:

λ> let f (Just a) = a 
λ> f (Just "hi") 
"hi" 
λ> f Nothing 
*** Exception: <interactive>:6:5-18: Non-exhaustive patterns in function f 

fromJust (проверить и бросить ошибки):

λ> fromJust (Just "hi") 
"hi" 
λ> fromJust Nothing 
*** Exception: Maybe.fromJust: Nothing 

Вы не можете использовать unsafeCoerce потому что для всех a внутренние представления Maybe a и a разные, и я не знал о способе рассказать GHC, чтобы не проверять другие случаи в неопровержимый рисунок.

Вы показали, что это поведение имеет нежелательных рабочих характеристик и что нет других, более простых оптимизаций? Если у вас нет, я бы не стал беспокоиться о . :)

Смежные вопросы