简体   繁体   中英

How to create a Haskell data structure containing polyvariadic functions?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM