How should I type and implement run
, so that the following statements work ?
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
All the polyvariadic functions in Run are of type Int -> ... -> Int: they take a variable number of Int arguments and yield a Int.
If it's any easier, I could live with a solution having a maximum number of arguments, eg 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))
How would you implement run
?
Since both f1
and f2
in your code have the same type Run
, the type checker can not distinguish between run f1
and run f2
which must have the same type.
This makes it hard to implement variadic functions properly.
It's much easier to use instead
data Run a = Run { run :: a }
so that f1
and f2
no longer share the same type.
If you only care about functions Int -> ... -> Int
there might be some solutions using type families, GADTs, DataKinds, and the like. This may be overkill, though, depending on what you are trying to realize.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.