绑定值不是第一个参数

时间:2012-07-25 12:07:37

标签: haskell currying

我有一个名为“Person”的课程

Person :: String -> String -> Int -> Gender -> Person

目标: 通过将性别分配给女性来制作更一般的Person版本,女性角色。

什么有效: 绑定前N个元素有效:

let personsWithNameAlice = Person "Alice"
let personsWithNameAliceMcGee = Person "Alice" "McGee"

什么行不通:

let femalePerson = Person {gender = Female}

问题:

  • 我该怎么做?
  • 如何将值绑定到n!= 0?
  • 的任何函数的第n个元素

只是我知道我可以在数学中写f(x,y,z)= g(x,y,z,5)而在C ++中写std :: bind2nd(f,8)所以不应该是可能在Haskell?

2 个答案:

答案 0 :(得分:13)

使用semantic editor combinators。 例如,假设您有一个函数:

foo :: Int -> String -> Bool -> Char -> Float
foo = undefined

我已经将示例更改为涉及所有不同类型,因此类型检查将确保我们的定义正确。 我们需要以下四种特化,每种特化都来自填充一个参数:

foo0 ::        String -> Bool -> Char -> Float  -- 3
foo1 :: Int ->           Bool -> Char -> Float  -- "hey"
foo2 :: Int -> String ->         Char -> Float  -- True
foo3 :: Int -> String -> Bool ->         Float  -- 'x'

第一个很简单,直接部分应用:

foo0 = foo 3

然而,让我们以奇怪的方式写出来(为了与其他人保持一致):

foo0 = ($ 3) foo

对于其他人,请使用result,这是作品的同义词:

result :: (b -> b') -> ((a -> b) -> (a -> b'))
result = (.)

result的应用程序将给定函数用于另一个函数的“结果”(因此直接类似于first中的secondControl.Arrow函数。 然后重复的应用程序瞄准多个结果,跳过连续的curried参数,完全按照我们的需要:

foo1 = result ($ "hey") foo
foo2 = (result.result) ($ True) foo
foo3 = (result.result.result) ($ 'x') foo

请注意,第n个专精使用result自己组合n次。

答案 1 :(得分:7)

你可以用lambda表达式来实现,给定

Person :: String -> String -> Int -> Gender -> Person

你要定义

femalePerson = \fn ln a -> Person fn ln a Female

或者,使用绑定中的参数:

femalePerson fn ln a = Person fn ln a Female

如果要特定绑定第二个参数,flip是您想要的功能

third = flip (/) 3

您可以使用flip绑定任意位置的参数,但这很快变得麻烦且难以理解:

femalePerson = curry . curry $ flip (uncurry (uncurry Person)) Female