ジェネリックプログラミング時間!実行時に型付き関数を部分的に適用する(任意の時間型が一致する)
私が機能している場合:
f :: a1 -> a2 -> a3 -> ... -> an
と値v
がための右のタイプがあるf
の引数のコンパイル時に知らず値
v :: aX -- where 1 <= x < n
を(もしあれば) 、部分的にf
をv
に適用できますか?
実行時に関数g
(下)を少し強固に構築できますか?それは実際に多形である必要はありません、私のすべての型は単形です!
g :: (a1 -> a2 -> a3 -> a4 -> a5) -> a3 -> (a1 -> a2 -> a4 -> a5)
g f v = \x y z -> f x y v z
私はTypeable(特にtypeRepArgs
)、v
はf
の第三引数であるが、それは私が部分的にf
を適用する方法が意味するものではありませんを使用して、ことを知っています。
私のコードは、おそらく次のようになります。
import Data.Typeable
data Box = forall a. Box (TyRep, a)
mkBox :: Typeable a => a -> Box
mkBox = (typeOf a, a)
g :: Box -> Box -> [Box]
g (Box (ft,f)) (Box (vt,v)) =
let argNums = [n | n <- [1..nrArgs], isNthArg n vt ft]
in map (mkBox . magicApplyFunction f v) argNums
isNthArg :: Int -> TyRep -> TyRep -> Bool
isNthArg n arg func = Just arg == lookup n (zip [1..] (typeRepArgs func))
nrArgs :: TyRep -> Int
nrArgs = (\x -> x - 1) . length . typeRepArgs
はmagicApplyFunction
を実装できることはありますか?
編集:私はついにこれを再生しました。私は今のところ、ここで全体のソリューションを書くつもりはない
buildFunc :: f -> x -> Int -> g
buildFunc f x 0 = unsafeCoerce f x
buildFunc f x i =
let !res = \y -> (buildFunc (unsafeCoerce f y) x (i-1))
in unsafeCoerce res
私が見る限り、** g **には何も問題はなく、多型も問題ではありません。関数と2番目の引数を持つたびにフリップを使うことができるのと同じように、あなたは知っています。 – Ingo
コンパイル時には 'g'がありません!実行時にどのように生成できますか? IIRC、私はヒントと前後に関数を渡すことができません –
th経由で適用する関数を書くことは問題ではありません。問題は戻り値(Dynamic/Box)はあなたは、あなたの唯一の選択肢を実現します。 – sclv