给定一个至少带有n参数的函数,我想旋转第一个参数,使其成为第n个参数。例如(在无类型的lambda演算中):

r(λa. a)                   = λa. a
r(λa. λb. a b)             = λb. λa. a b
r(λa. λb. λc. a b c)       = λb. λc. λa. a b c
r(λa. λb. λc. λd. a b c d) = λb. λc. λd. λa. a b c d

等等。

可以用通用方式编写r吗?如果您知道n >= 2怎么办?

这是Scala中所述的问题:
trait E
case class Lam(i: E => E) extends E
case class Lit(i: Int) extends E
case class Ap(e: E, e: E) extends E

例如,旋转应采用Lam(a => Lam(b => Lam(c => Ap(Ap(a, b), c))))并返回Lam(b => Lam(c => Lam(a => Ap(Ap(a, b), c))))

最佳答案

技巧是标记所涉及函数的“最终”值,因为对于普通的haskell来说,a -> ba -> (b->c)都只是单个变量的函数。
但是,如果这样做,我们可以做到。

{-# LANGUAGE TypeFamilies,FlexibleInstances,FlexibleContexts #-}
module Rotate where

data Result a = Result a

class Rotate f where
  type After f
  rotate :: f -> After f

instance Rotate (a -> Result b) where
  type After (a -> Result b) = a -> Result b
  rotate = id

instance Rotate (a -> c) => Rotate (a -> b -> c) where
  type After (a -> b -> c) = b -> After (a -> c)
  rotate = (rotate .) . flip

然后,查看其实际效果:
f0 :: Result a
f0 = Result undefined

f1 :: Int -> Result a
f1 = const f0

f2 :: Char -> Int -> Result a
f2 = const f1

f3 :: Float -> Char -> Int -> Result a
f3 = const f2

f1' :: Int -> Result a
f1' = rotate f1

f2' :: Int -> Char -> Result a
f2' = rotate f2

f3' :: Char -> Int -> Float -> Result a
f3' = rotate f3

关于scala - 将第一个参数旋转到函数成为第n个,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/5188212/

10-16 01:49