せずに機能をn回呼び出すために、タイプが各繰り返し関数呼び出しの後に変更することを可能にする折り目を作成すると、hereは再帰
dfold
:: KnownNat k
=> Proxy (p :: TyFun Nat * -> *)
-> (forall l. SNat l -> a -> (p @@ l) -> p @@ (l + 1))
-> (p @@ 0)
-> Vec k a
-> p @@ k
を定義された基本的には倍になりますサイクルごとに新しいタイプを返すことができます。で
bitonicSort
:: forall n a. (KnownNat n, Ord a)
=> (Vec n a -> Vec n a) --^The recursive step
-> (Vec (2 * n) a -> Vec (2 * n) a) --^Merge step
-> Vec (2 * n) a --^Input vector
-> Vec (2 * n) a --^Output vector
bitonicMerge
:: forall n a. (Ord a , KnownNat n)
=> (Vec n a -> Vec n a) --^The recursive step
-> Vec (2 * n) a --^Input vector
-> Vec (2 * n) a --^Output vector
例を使用:とdfoldが発生するタイプのために重要である https://github.com/adamwalker/clash-utils/blob/master/src/CLaSH/Sort.hs
I二つの機能:私はこのプロジェクトで定義されたbitonicSortを一般化しようとしています
上記のプロジェクトは:
bitonicSorterExample
:: forall a. (Ord a)
=> Vec 16 a --^Input vector
-> Vec 16 a --^Sorted output vector
bitonicSorterExample = sort16
where
sort16 = bitonicSort sort8 merge16
merge16 = bitonicMerge merge8
sort8 = bitonicSort sort4 merge8
merge8 = bitonicMerge merge4
sort4 = bitonicSort sort2 merge4
merge4 = bitonicMerge merge2
sort2 = bitonicSort id merge2
merge2 = bitonicMerge id
私は先に行ったdはより一般的なバージョンを作った。指定したサイズのベクトルを持つ作品と
bSort16 :: Ord a => Vec 16 a -> Vec 16 a
bSort16 = fst $ genBitonic $ genBitonic $ genBitonic $ genBitonic bitonicBase
bSort8 :: Ord a => Vec 8 a -> Vec 8 a
bSort8 = fst $ genBitonic $ genBitonic $ genBitonic bitonicBase
bSort4 :: Ord a => Vec 4 a -> Vec 4 a
bSort4 = fst $ genBitonic $ genBitonic bitonicBase
bSort2 :: Ord a => Vec 2 a -> Vec 2 a
bSort2 = fst $ genBitonic bitonicBase
各ソート:私は速いので、同じように新しいバイトニックソートを行うことができますこのバージョンで
genBitonic :: (Ord a, KnownNat n) =>
(Vec n a -> Vec n a, Vec (2 * n) a -> Vec (2 * n) a)
-> (Vec (2 * n) a -> Vec (2 * n) a, Vec (4 * n) a -> Vec (4 * n) a)
genBitonic (bSort,bMerge) = (bitonicSort bSort bMerge, bitonicMerge bMerge)
bitonicBase :: Ord a => (Vec 1 a -> Vec 1 a, Vec 2 a -> Vec 2 a)
bitonicBase = (id, bitonicMerge id)
。
testVec16 :: Num a => Vec 16 a
testVec16 = 9 :> 2 :> 8 :> 6 :> 3 :> 7 :> 0 :> 1 :> 4 :> 5 :> 2 :> 8 :> 6 :> 3 :> 7 :> 0 :> Nil
testVec8 :: Num a => Vec 8 a
testVec8 = 9 :> 2 :> 8 :> 6 :> 3 :> 7 :> 0 :> 1 :> Nil
testVec4 :: Num a => Vec 4 a
testVec4 = 9 :> 2 :> 8 :> 6 :> Nil
testVec2 :: Num a => Vec 2 a
testVec2 = 2 :> 9 :> Nil
クイックノート:
私は "bitonicBase" のt倍に "genBitonic" を適用しようとしています。
私はVHDLにこれを合成するために衝突を使用していますので、私がt回
を適用するために再帰を使用することはできません我々は常に同じサイズ
のVECにしてVECサイズ2^tでソートされます
「はVecとをNa」サイズnのベクトルであり、Iは、所与Vecとする機能を生成する関数を作りたい
を入力します。私はdfoldまたはdtfoldを使うと正しいパスであると信じています。
私は、機能genBitonic
のようなもので折り畳みをしたいと思っていました。
次に、fst
を使用して、ソートに必要な機能を取得します。
私は2つの可能な設計だった:
ワンを:それはベースをとる関数を得るために組成物を使用して折りたたみます。
bSort8 :: Ord a => Vec 8 a -> Vec 8 a
bSort8 = fst $ genBitonic.genBitonic.genBitonic $ bitonicBase
それは
**If composition was performed three times**
foo3 ::
(Ord a, KnownNat n) =>
(Vec n a -> Vec n a, Vec (2 * n) a -> Vec (2 * n) a)
-> (Vec (2 * (2 * (2 * n))) a -> Vec (2 * (2 * (2 * n))) a,
Vec (4 * (2 * (2 * n))) a -> Vec (4 * (2 * (2 * n))) a)
二ような何かをもたらしただろうベースは答えた前に: セカンドアイデアは上の蓄積を開始する値bとしてbitonicBaseを使用することでした。これは私がfst
を適用する前にそれが必要な形で直接生じたはずです。
編集 vecAcum
はちょうどdfold
の内側に構築値であることを意味します。
genBitonic :: (Ord a, KnownNat n) =>
(Vec n a -> Vec n a, Vec (2 * n) a -> Vec (2 * n) a)
-> (Vec (2 * n) a -> Vec (2 * n) a, Vec (4 * n) a -> Vec (4 * n) a)
:彼らは私がやりたいことのように2つの関数のタプルを取るあるリスト演算子
:
>>> :t (:>)
(:>) :: a -> Vec n a -> Vec (n + 1) a
の単なるベクトル形式である:>
を使用して倍dfold例で
それを構成します。 のでgenBitonic . genBitonic
はタイプだろう:それでは基本機能は、タイプを固化何だろう
(Vec n a -> Vec n a, Vec (2 * n) a -> Vec (2 * n) a)
-> (Vec (2 * (2 * n)) a -> Vec (2 * (2 * n)) a, Vec (4 * (2 * n)) a -> Vec (4 * (2 * n)) a)
を。例:
bitonicBase :: Ord a => (Vec 1 a -> Vec 1 a, Vec 2 a -> Vec 2 a)
bitonicBase = (id, bitonicMerge id)
bSort4 :: Ord a => Vec 4 a -> Vec 4 a
bSort4 = fst $ genBitonic $ genBitonic bitonicBase
私は長さnのベクトルに再帰を行うことと等価である長さnのベクトルのための機能を構築するためにdfoldを使用しています。
私が試した:
を私はdfold
data SplitHalf (a :: *) (f :: TyFun Nat *) :: *
type instance Apply (SplitHalf a) l = (Vec (2^l) a -> Vec (2^l) a, Vec (2^(l + 1)) a -> Vec (2^(l + 1)) a)
generateBitonicSortN2 :: forall k a . (Ord a, KnownNat k) => SNat k -> Vec (2^k) a -> Vec (2^k) a
generateBitonicSortN2 k = fst $ dfold (Proxy :: Proxy (SplitHalf a)) vecAcum base vecMath
where
vecMath = operationList k
vecAcum :: (KnownNat l, KnownNat gl, Ord a) => SNat l
-> (SNat gl -> SplitHalf a @@ gl -> SplitHalf a @@ (gl+1))
-> SplitHalf a @@ l
-> SplitHalf a @@ (l+1)
vecAcum l0 f acc = undefined -- (f l0) acc
base :: (Ord a) => SplitHalf a @@ 0
base = (id,id)
general :: (KnownNat l, Ord a)
=> SNat l
-> SplitHalf a @@ l
-> SplitHalf a @@ (l+1)
general _ (x,y) = (bitonicSort x y, bitonicMerge y)
operationList :: (KnownNat k, KnownNat l, Ord a)
=> SNat k
-> Vec k
(SNat l
-> SplitHalf a @@ l
-> SplitHalf a @@ (l+1))
operationList k0 = replicate k0 general
の下にリストされている例に従うことをしようとした私は、dfoldソースコードは
{-# LANGUAGE BangPatterns #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MagicHash #-}
{-# LANGUAGE PatternSynonyms #-}
{-# LANGUAGE Rank2Types #-}
{-# LANGUAGE ScopedTypeVariables #-}
{-# LANGUAGE TemplateHaskell #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE ViewPatterns #-}
{-# LANGUAGE Trustworthy #-}
エラーメッセージを使用して拡張を使用しています:
Sort.hs:182:71: error:
* Could not deduce (KnownNat l) arising from a use of `vecAcum'
from the context: (Ord a, KnownNat k)
bound by the type signature for:
generateBitonicSortN2 :: (Ord a, KnownNat k) =>
SNat k -> Vec (2^k) a -> Vec (2^k) a
at Sort.hs:181:1-98
Possible fix:
add (KnownNat l) to the context of
a type expected by the context:
SNat l
-> (SNat l0
-> (Vec (2^l0) a -> Vec (2^l0) a,
Vec (2^(l0 + 1)) a -> Vec (2^(l0 + 1)) a)
-> (Vec (2^(l0 + 1)) a -> Vec (2^(l0 + 1)) a,
Vec (2^((l0 + 1) + 1)) a -> Vec (2^((l0 + 1) + 1)) a))
-> SplitHalf a @@ l
-> SplitHalf a @@ (l + 1)
* In the second argument of `dfold', namely `vecAcum'
In the second argument of `($)', namely
`dfold (Proxy :: Proxy (SplitHalf a)) vecAcum base vecMath'
In the expression:
fst $ dfold (Proxy :: Proxy (SplitHalf a)) vecAcum base vecMath
Sort.hs:182:84: error:
* Could not deduce (KnownNat l0) arising from a use of `vecMath'
from the context: (Ord a, KnownNat k)
bound by the type signature for:
generateBitonicSortN2 :: (Ord a, KnownNat k) =>
SNat k -> Vec (2^k) a -> Vec (2^k) a
at Sort.hs:181:1-98
The type variable `l0' is ambiguous
* In the fourth argument of `dfold', namely `vecMath'
In the second argument of `($)', namely
`dfold (Proxy :: Proxy (SplitHalf a)) vecAcum base vecMath'
In the expression:
fst $ dfold (Proxy :: Proxy (SplitHalf a)) vecAcum base vecMath
Failed, modules loaded: none.
** EDIT ** さらに詳しい情報が追加されました。
http://chat.stackoverflow.com/rooms(私たちは、[チャットでこの議論を続ける]してみましょう/ 135612/discussion-between-lambdascientist-and-user2407038)。 – LambdaScientist
正確に何かを入力しようとしていますか(おそらく 'generateBitonicSortN2'の本文)?どの機能があなたの提案した解決策の一部であるか、実際の問題は何か、ハードな制約です。 – Alec