Reputation:
I'm working on some Haskell code and I want to define a type that takes two KnownNat
and results in the smallest factor of the second KnownNat
that is greater then the first.
For instance given the numbers 13
and 100
the result would be 20
since 20
divides 100
cleanly and there is no number between 13
and 20
that divides 100
cleanly. Another example is given 96
and 10000
the result would be 100
.
The way I wanted to express this in Haskell is to somehow use the typelits package to compute it. But I can't really figure out how.
type a b = ...?
Any help or pointers are appreciated!
Upvotes: 1
Views: 85
Reputation: 152837
Shouldn't be too hard. The standard trial-division algorithm, lifted to the type level, seems to do the trick.
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
import GHC.TypeLits
type FactorGT a b = FactorGTRaw a b (CmpNat (Mod b a) 0)
type family FactorGTRaw a b v where
FactorGTRaw a b EQ = a
FactorGTRaw a b _ = FactorGT (a+1) b
Try it out in ghci:
> :k! FactorGT 13 100
FactorGT 13 100 :: Nat
= 20
> :k! FactorGT 96 1000
FactorGT 96 1000 :: Nat
= 100
Upvotes: 2