我是Haskell的新手,我正在尝试理解在Haskell中创建的游戏(tic tac toe)。我知道如果一个函数需要n个参数,那么你必须在函数定义中提供n个参数。例如:
f :: Int -> Int -> String
f a b = "This function makes no sense"
但是在这个Haskell脚本中有一个函数需要两个参数,但在定义中它没有。当然,它正在发挥作用,但我似乎无法弄清楚原因。
import Data.Map qualified as M
type Board = M.Map (Int, Int) Marker
data Marker = X | O | Blank deriving Eq
getMarker :: Board -> (Int, Int) -> Marker
getMarker = flip $ M.findWithDefault Blank
关于这个函数的作用的任何想法,更重要的是,为什么它有效(你可以看到getMarker
在最后一行占用0个参数)?
答案 0 :(得分:4)
误解在于:
...(你可以看到
getMarker
在最后一行占用0个参数)......
令你困惑的是partial application。
getMarker :: Board -> (Int, Int) -> Marker
getMarker = flip $ M.findWithDefault Blank
最后一行实际告诉你的是getMarker
flip $ M.findWithDefault Blank
。
或者,更准确地说,getMarker
求值为应用于 getMarker
参数的声明类型的函数。
答案 1 :(得分:1)
你有getMarker :: Board -> (Int, Int) -> Marker
,所以它被称为
getMarker board pos
由于你有getMarker = flip $ M.findWithDefault Blank
,这相当于:
(flip $ M.findWithDefault Blank) board pos
扩展$
:
(flip (M.findWithDefault Blank)) board pos
功能应用程序是左关联的,因此(f x) y
等同于f x y
。
flip (M.findWithDefault Blank) board pos
flip f x y
相当于f y x
,因此表达式等于:
(M.findWithDefault Blank) pos board
再次,感谢函数应用程序的左关联性:
M.findWithDefault Blank pos board
这是明智的。