簡體   English   中英

將類型級別自然數轉換為常規數

[英]Converting a type level natural number into a regular number

我試圖通過一個實現點積的簡單例子來獲得類型級自然數的懸念。 我代表這樣的點積:

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

現在,我可以為點積的每個單獨大小創建一個monoid實例(其中mappend是實際的點積),如下所示:

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

但我想定義一個更通用的實例,如下所示:

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

我不確定如何將類型的數字轉換為我可以在mempty函數中使用的常規數字。


編輯:有一個函數dotplength :: (DotP n) -> n在時間O(1)中運行,只需查看它是什么類型,而不是遍歷整個列表也很酷。

要獲得與類型級別自然n對應的Integer ,您可以使用

fromSing (sing :: Sing n) :: Integer

在擺弄了一下后,我得到了這個編譯:

{-# 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)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM