2016-07-03 5 views
3

Ich möchte das niedrigstwertige Setzbit eines beliebigen Bits löschen. Das Problem ist, dass ich nicht unbedingt die Num Instanz habe, also x.&.(x-1) ist keine Option. Die einzige Funktion, die ich denken konnte, ist dies:Lösche das niederwertigste Setzbit

clearLsb x = x `clearBit` countTrailingZeros x 

ich es gegen die x&(x-1) Version gebenchmarkt, und es ist 1,5 langsamer auf Word32 und Word64 unabhängig von der Höhe der Optimierung. Ich würde mich freuen, wenn jemand einen cleveren Hack dafür kennt.

+0

Sie Arithmetik mit logischen Operationen emulieren können, aber bezweifeln es schneller ist. – augustss

+1

Ich kann nicht vermeiden, mich zu wundern, warum Sie die 'Num'-Subtraktion und die von Ihnen gepostete Formel nicht verwenden können. – chi

+1

@chi, weil ich einen Typ wie Datenmaske haben könnte = Maske Word Word ..., für die es ganz natürlich wäre, eine Bits-Instanz zu machen, aber Num ist viel mehr beteiligt. – lanskey

Antwort

3

können Sie überlasten die Funktion die effizientere Umsetzung auf der Typebene, wählen, wenn es verfügbar ist. Dazu muss eine Typklasse hinzugefügt werden, aber selbst mit der countTrailingZeros Implementierung müssen Sie bereits einige Typklassenbeschränkungen für Ihre Funktion definieren (nämlich FiniteBits) (1).

Insbesondere mit einigen Spracherweiterungen, alle Num Typen können eingestellt a .&. (a - 1) Gleichung verwenden (2):

{-# LANGUAGE FlexibleInstances, UndecidableInstances #-} 

import Data.Bits (Bits, (.&.)) 

class LSB a where 
    clear :: a -> a 

instance (Bits a, Num a) => LSB a where 
    clear a = a .&. (a - 1) -- more efficient implementation 

newtype Foo = ... -- some type not instance of Num 

instance LSB Foo where 
    clear a = ... -- some other approach 

1. beachten Sie auch tun, mit countTrailingZeros Sie Ausschluss Integer Typ, das ist countTrailingZeros (16 :: Integer) wird nicht Typ überprüfen, da es keine Instanz von FiniteBits ist.
2. Obwohl wäre besser, explizit Instanzen zu schreiben, als diese Erweiterungen Sprache verwendet

+1

'FiniteBits' wurde furchtbar benannt, IMO. Es hätte "FixedBits" oder so heißen sollen. 'FiniteBits' sollten Typen zugelassen haben, deren Werte jeweils endlich viele Bits haben. – dfeuer

+0

Die typeclass Lösung sieht für den Zweck am besten aus. Aber verletzt es nicht irgendwie die Philosophie hinter Haskell typeclasses? Es fügt keine neue Abstraktion, keine interessanten algebraischen Gesetze hinzu. Obwohl es eine nette Ergänzung zum Bits-Paket gewesen wäre (ich meine die Funktion, nicht die Typenklasse). – lanskey

+1

@lanskey typeclasses sind der Mechanismus, den harkell verwendet, um * Ad-hoc-Polymorphismus * bereitzustellen. Gewöhnlich beinhaltet dies eine Abstraktion, aber es gibt Fälle, wo Sie nur den Ad-hoc-Polymorphismus wünschen, d. H. In der Lage sein, eine Methode für verschiedene Typen zu implementieren und generischen Code zu schreiben, der das Richtige tut. Dies scheint einer dieser Fälle zu sein. – Bakuriu