我有一个名为"人"的班级
Person :: String -> String -> Int -> Gender -> Person
Run Code Online (Sandbox Code Playgroud)
目标: 通过将性别分配给女性来制作更一般的人物版本,女性角色.
什么有效: 绑定前N个元素有效:
let personsWithNameAlice = Person "Alice"
let personsWithNameAliceMcGee = Person "Alice" "McGee"
Run Code Online (Sandbox Code Playgroud)
什么行不通:
let femalePerson = Person {gender = Female}
Run Code Online (Sandbox Code Playgroud)
题:
只是我知道我可以在数学中编写f(x,y,z)= g(x,y,z,5),在C++中编写std :: bind2nd(f,8)所以不应该在Haskell中编写?
Con*_*nal 13
使用语义编辑器组合器.例如,假设您有一个功能:
foo :: Int -> String -> Bool -> Char -> Float
foo = undefined
Run Code Online (Sandbox Code Playgroud)
我已经将示例更改为涉及所有不同类型,因此类型检查将确保我们的定义正确.我们需要以下四种特化,每种特殊化都来自填充一个参数:
foo0 :: String -> Bool -> Char -> Float -- 3
foo1 :: Int -> Bool -> Char -> Float -- "hey"
foo2 :: Int -> String -> Char -> Float -- True
foo3 :: Int -> String -> Bool -> Float -- 'x'
Run Code Online (Sandbox Code Playgroud)
第一个很容易,直接部分应用:
foo0 = foo 3
Run Code Online (Sandbox Code Playgroud)
但是,让我们以奇怪的方式写它(为了与其他人保持一致):
foo0 = ($ 3) foo
Run Code Online (Sandbox Code Playgroud)
对于其他人,使用result,这是组成的同义词:
result :: (b -> b') -> ((a -> b) -> (a -> b'))
result = (.)
Run Code Online (Sandbox Code Playgroud)
result将给定函数的目标应用于另一个函数的"结果"(因此直接类似于函数first和second函数Control.Arrow).然后重复的应用程序瞄准多个结果,跳过连续的curried参数,正如我们所需:
foo1 = result ($ "hey") foo
foo2 = (result.result) ($ True) foo
foo3 = (result.result.result) ($ 'x') foo
Run Code Online (Sandbox Code Playgroud)
请注意,第n个专业化使用result自身组合n次.
你可以用lambda表达式来实现
Person :: String -> String -> Int -> Gender -> Person
Run Code Online (Sandbox Code Playgroud)
你定义了
femalePerson = \fn ln a -> Person fn ln a Female
Run Code Online (Sandbox Code Playgroud)
或者,在绑定中使用参数:
femalePerson fn ln a = Person fn ln a Female
Run Code Online (Sandbox Code Playgroud)
如果要特定绑定第二个参数,flip则是您想要的功能
third = flip (/) 3
Run Code Online (Sandbox Code Playgroud)
您可以使用flip绑定任意位置的参数,但这很快变得麻烦且难以理解:
femalePerson = curry . curry $ flip (uncurry (uncurry Person)) Female
Run Code Online (Sandbox Code Playgroud)