Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting a type level natural number into a regular number

Tags:

types

haskell

I'm trying to get the hang of type level natural numbers with a simple example of implementing a dot product. I represent the dot product like this:

data DotP (n::Nat) = DotP [Int]
    deriving Show

Now, I can create a monoid instance (where mappend is the actual dot product) for each individual size of the dot product like this:

instance Monoid (DotP 0) where
    mempty                      = DotP $ replicate 0 0
    mappend (DotP xs) (DotP ys) = DotP $ zipWith (*) xs ys

instance Monoid (DotP 1) where
    mempty                      = DotP $ replicate 1 0
    mappend (DotP xs) (DotP ys) = DotP $ zipWith (*) xs ys

instance Monoid (DotP 2) where
    mempty                      = DotP $ replicate 2 0
    mappend (DotP xs) (DotP ys) = DotP $ zipWith (*) xs ys

But I want to define a much more general instance like this:

instance Monoid (DotP n) where
    mempty                      = DotP $ replicate n 0
    mappend (DotP xs) (DotP ys) = DotP $ zipWith (*) xs ys

I'm not sure how to convert the type's number into a regular number that I can work with inside the mempty function.


Edit: It would also be cool to have a function dotplength :: (DotP n) -> n that ran in time O(1) by just looking up what type it is, rather than having to traverse the whole list.

like image 418
Mike Izbicki Avatar asked Oct 16 '12 23:10

Mike Izbicki


People also ask

How do you make a natural number?

As we know already, natural numbers start with 1 to infinity and are positive integers. But when we combine 0 with a positive integer such as 10, 20, etc. it becomes a natural number. In fact, 0 is a whole number which has a null value.

Is 7.0 a natural number?

Natural Numbers The numbers that we use when we are counting or ordering {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 …} Whole Numbers The numbers that include natural numbers and zero. Not a fraction or decimal. {0, 2, 3, 4, 5 6, 7, 8, 9, 10, 11 …}

How do you identify a natural number?

Natural numbers are all numbers 1, 2, 3, 4… They are the numbers you usually count and they will continue on into infinity. Whole numbers are all natural numbers including 0 e.g. 0, 1, 2, 3, 4… Integers include all whole numbers and their negative counterpart e.g. …


1 Answers

To get the Integer corresponding to the type level natural n, you can use

fromSing (sing :: Sing n) :: Integer

After fiddling around a bit, I got this to compile:

{-# LANGUAGE DataKinds, KindSignatures, ScopedTypeVariables #-}

import Data.Monoid
import GHC.TypeLits

data DotP (n :: Nat) = DotP [Int]
    deriving Show

instance SingI n => Monoid (DotP n) where
    mempty = DotP $ replicate (fromInteger k) 0
      where k = fromSing (sing :: Sing n)

    mappend (DotP xs) (DotP ys) = DotP $ zipWith (*) xs ys

dotplength :: forall n. SingI n => DotP n -> Integer
dotplength _ = fromSing (sing :: Sing n)
like image 73
hammar Avatar answered Oct 05 '22 12:10

hammar