编程成本函数的最佳方法(关联函数 - 值)

时间:2017-05-27 20:26:27

标签: haskell search pattern-matching

我正在尝试在Haskell中编写成本函数,但似乎我高估了模式匹配的功能。这是我已定义的代码:

-- Directions for the movement
data Direction = North | East | West | South deriving (Show, Eq)

-- An `Action` gets a Coord and returns another Coord if possible
type Action = Coord -> Maybe Coord

-- Move function; `move North` is an Action
move :: Direction -> Action
move d (x, y) = ...

我的主要问题是现在我必须定义Cost函数,以便:

type Cost = Coord -> Action -> Double

如果我想要一个只检查方向以返回成本的简单成本函数,我想到的第一个想法是利用模式匹配,但这是无效的语法(说实话,它看起来很公平):

mazeCost :: Cost
mazeCost (x, y) (move East) = 3
mazeCost (x, y) (move West) = 5
-- ... And on and on

我当前的解决方案涉及计算目标状态并将其与每个操作的结果进行比较,以检查这是否是作为参数传递的函数,但这看起来很简陋,而不是超级简短,我认为可能存在在Haskell中更好的方法:

mazeCost :: Cost
mazeCost coord action
  | destination == east   = 1
  | destination == west   = 2
  | destination == north  = 3
  | destination == south  = 0
  where destination = action coord
        east  = move East  coord
        west  = move West  coord
        south = move South coord
        north = move North coord

是否有更好的方法将函数(Coord -> Direction -> Maybe Coord)与成本值(Double)相关联?这是我尝试编写的最小示例,如果示例代码中存在任何不一致或者某些内容不明确,请询问。

2 个答案:

答案 0 :(得分:1)

你几乎就在那里,你只需要ViewPatterns

{-# LANGUAGE ViewPatterns ... #-}
...
move ((x,y), d) = ... Just (d,...) ...

moveCost = curry moveCost' where
    moveCost' (move -> Just (East, (x,y))) = ...
    moveCost' (move -> Just (West, (x,y))) = ...

请注意,我们在此处更改了move的类型。视图模式仅适用于返回我们实际可以匹配的模式的单个参数函数,因此它必须作为元组传递((x,y),d),这意味着moveCost'必须接受元组,但我们可以只是咖喱它带有包装函数。

答案 1 :(得分:0)

?- read_gold(100, Solutions). Solutions = [[3, 97], [11,89], ...] 需要CostCoord。但是,由于操作需要协调和方向,并且范围没有方向,因此您无法实际使用该操作。您需要将操作应用于坐标方向以获取值。所以Action的唯一实现是完全忽略该动作的实现,而不是你想要的。

但是,如果你有某种方向的指示,那么你可以将它(和坐标)应用到动作。一种方法是通过currying。函数mazeCost是一个获取方向并为该方向提供成本函数的函数

Direction -> Cost

我认为这是一个很好的例子,说明部分应用程序类似于引入闭包:mazeCost :: Direction -> Cost mazeCost dir coord act = case act coord dir of Just (x', y') -> 0 -- or whatever the cost is Nothing -> 0 -- or whatever the cost is 是一个关闭mazeCost East Direction的函数,并给出{{ 1}}为那个方向。

我还应该注意,我看不出您提出的解决方案如何进行类型检查。如果您未指定East,则表达式Costtype Action = Coord -> Direction -> Maybe Coord类型的函数,而不是“目标”。如果我误解了它并且确实进行了类型检查,那么它仍然是一个部分函数,​​如果该行为不等同于其中一个action coord中的简单Direction -> Maybe Coord,则会导致运行时错误,如luqui暗示的那样。