通用编程时间!
如果我有一个功能:
f :: a1 -> a2 -> a3 -> ... -> an
和一个值
v :: aX -- where 1 <= x < n
f
在编译时不知道值的哪个参数v
是正确的类型(如果有的话),我可以部分适用f
于v
吗?(使用 Typeable、Data、TH 或任何其他技巧)
稍微更扎实一点,我可以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