How do I write a Data.Vector.Unboxed instance in Haskell?
Asked Answered
B

1

17

I've got a numeric application that does a lot of work with negative logs of probabilities, which (since probabilities range from zero to one) take the values of positive doubles, or negative infinity (if the underlying probability was zero).

I'm using these with a newtype Score as follows:

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

Now, in an implementation of the Viterbi algorithm, I've been using Data.Vector a lot, and indeed I have some Data.Vectors of Scores. While trying to do some performance tuning, I decided to try using Data.Vector.Unboxed. However, I need to write an instance for Unbox, which cannot be derived, and I can't quite figure out what I need to do (particularly, what the contract for the Unbox typeclass is). Since Score is really a Double with some useful constructors and semantics, this should be possible, I'd think. As far as I can tell, I need to be able to tell Data.Vector.Unboxed how big each slot in a vector of Scores must be, and I guess how to read and write them (but heck, they're a lot like Doubles).

So, what do I do? Thanks!

Boyish answered 2/6, 2012 at 23:22 Comment(0)
P
15

The Unbox type class doesn't have any methods -- it's just shorthand for the Vector and MVector type classes. Derive those, and the Unbox class comes for free (either via deriving or by just writing instance U.Unbox Score on its own line somewhere).

{-# 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)
Potman answered 2/6, 2012 at 23:29 Comment(3)
This no longer works in ghc 7.8.4, giving 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)Fidelis
ghc.haskell.org/trac/ghc/ticket/9112 seems relevant, though I don't see that they mention a solution.Fidelis
As unhammer has ponted out, this solution doesn't work anymore since GHC-7.8. Apparently the recommended way is to use vector-th-unbox until the underlying GHC issue is resolved.Emplane

© 2022 - 2024 — McMap. All rights reserved.