我有一个名为“Person”的课程
Person :: String -> String -> Int -> Gender -> Person
目标: 通过将性别分配给女性来制作更一般的Person版本,女性角色。
什么有效: 绑定前N个元素有效:
let personsWithNameAlice = Person "Alice"
let personsWithNameAliceMcGee = Person "Alice" "McGee"
什么行不通:
let femalePerson = Person {gender = Female}
问题:
只是我知道我可以在数学中写f(x,y,z)= g(x,y,z,5)而在C ++中写std :: bind2nd(f,8)所以不应该是可能在Haskell?
答案 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
中的second
和Control.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