Как мне написать экземпляр Data.Vector.Unboxed в Haskell?

У меня есть числовое приложение, которое много работает с отрицательными логарифмами вероятностей, которые (поскольку вероятности варьируются от нуля до единицы) принимают значения положительных удвоений или отрицательной бесконечности (если базовая вероятность равна нулю).

Я использую их с newtype Score следующим образом:

newtype Score = Score Double
  deriving (Eq, Ord)
 -- ^ A "score" is the negated logarithm of a probability

negLogZero :: Score -- ^ Stands in for - log 0
negLogZero = Score 10e1024

negLogOne :: Score -- ^ - log 1
negLogOne = Score 0.0

unScore :: Score -> Double
unScore (Score x) = x

instance Show Score where
  show (Score x) = show x

Теперь, в реализации алгоритма Витерби, я много использовал Data.Vector, и действительно, у меня есть несколько Data.Vector из Score. Пытаясь настроить производительность, я решил попробовать использовать Data.Vector.Unboxed. Однако мне нужно написать экземпляр для Unbox, который не может быть получен, и я не могу понять, что мне нужно делать (в частности, каков контракт для класса типов Unbox). Поскольку Score на самом деле Double с некоторыми полезными конструкторами и семантикой, я думаю, это должно быть возможно. Насколько я могу судить, мне нужно быть в состоянии сказать Data.Vector.Unboxed, насколько большим должен быть каждый слот в векторе Score, и я предполагаю, как их читать и записывать (но, черт возьми, они очень похожи на Double).

Итак, что мне делать? Спасибо!


person Noah Daniels    schedule 02.06.2012    source источник


Ответы (1)


Класс типа Unbox не имеет никаких методов - это просто сокращение для классов типов Vector и MVector. Получите их, и класс Unbox появится бесплатно (либо путем наследования, либо просто написав где-нибудь instance U.Unbox Score в отдельной строке).

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Data.Vector.Generic.Base
import Data.Vector.Generic.Mutable
import qualified Data.Vector.Unboxed as U
newtype Score = Score Double deriving (Vector U.Vector, MVector U.MVector, U.Unbox)
person Daniel Wagner    schedule 02.06.2012
comment
Это больше не работает в ghc 7.8.4, давая Could not coerce from ‘Data.Vector.Primitive.Vector Double’ to ‘U.Vector Score’ because ‘Data.Vector.Primitive.Vector Double’ and ‘U.Vector Score’ are different types. arising from the coercion of the method ‘Data.Vector.Generic.Base.basicLength’ from type ‘U.Vector Double -> Int’ to type ‘U.Vector Score -> Int’ Possible fix: use a standalone 'deriving instance' declaration, so you can specify the instance context yourself When deriving the instance for (Vector U.Vector Score) - person unhammer; 06.12.2016
comment
ghc.haskell.org/trac/ghc/ticket/9112 кажется актуальным, хотя я не вижу, чтобы они упоминали решение. - person unhammer; 06.12.2016
comment
Как показал unhammer, это решение больше не работает, начиная с GHC-7.8. Очевидно, что рекомендуется использовать vector-th-unbox, пока не будет решена основная проблема GHC. - person sjakobi; 10.12.2016