我应该如何键入和实现run
,以便以下语句有效?
data Run = Run {run :: ??}
f1 = Run (\x -> x)
f2 = Run (\x y-> x+y)
f3 = Run (\x y z -> x*(y+z))
print $ run f1 1 :: Int --> 1
print $ run f2 1 2 :: Int --> 3
print $ run f3 1 2 3 :: Int -> 5
Run中的所有polyvariadic functions都是Int - > ... - > Int:它们采用可变数量的Int参数并产生一个Int。
如果它更容易,我可以使用具有最大数量参数的解决方案,例如: 3:
data Run
= Run1 (Int -> Int)
| Run2 (Int -> Int -> Int)
| Run3 (Int -> Int -> Int -> Int)
f1 = Run1 (\x -> x)
f2 = Run2 (\x y-> x+y)
f3 = Run3 (\x y z -> x*(y+z))
你会如何实施run
?
由于代码中的f1
和f2
都具有相同类型的Run
,因此类型检查器无法区分必须具有相同类型的run f1
和run f2
。
这使得很难正确地实现可变参数功能。
相反,它更容易使用
data Run a = Run { run :: a }
所以f1
和f2
不再拥有相同的类型。
如果您只关心函数Int -> ... -> Int
,可能会有一些使用类型族,GADT,DataKinds等的解决方案。但这可能有点过分,取决于你想要实现的目标。