我应该如何键入和实现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
?
答案 0 :(得分:2)
由于代码中的f1
和f2
具有相同的类型Run
,因此类型检查器无法区分必须具有以下两种类型的run f1
和run f2
相同的类型。
这使得很难正确实现可变参数功能。
使用起来更容易
data Run a = Run { run :: a }
以便f1
和f2
不再共享同一类型。
如果您只关心函数Int -> ... -> Int
,则可能有一些使用类型族,GADT,DataKind等的解决方案。但是,根据您要实现的目标,这可能是过大的。