Как отловить и проигнорировать вызов Error в Haskell - PullRequest
3 голосов
/ 05 октября 2019

Я пытаюсь понять, как обрабатывать ошибки вызовов в Haskell. Например: у меня есть этот график

import Data.Map (Map,empty,member,insert,keys,(!))
import Graphviz

-- | A directed graph
data Graph v = Graph
    { arcsMap :: Map v [v]     -- A map associating a vertex with its successors
    , labelMap :: Map v String -- The Graphviz label of each node
    , styleMap :: Map v String -- The Graphviz style of each node
    }deriving (Show,Eq, Ord)

И у меня есть функция

-- | Returns the successors of a vertex in a graph in ascending order
--
-- We say that `v` is a successor of `u` in a graph `G` if the arc `(u,v)`
-- belongs to `G`.
--
-- Note: Returns the empty list if the vertex does not belong to the graph.
--
-- >>> successors 1 emptyGraph
-- []
-- >>> successors 1 $ addArc (1,2) emptyGraph
-- [2]
-- >>> successors 1 $ addArcs emptyGraph [(1,2),(2,3),(1,3)]
-- [2,3]
successors :: Ord v => v -> Graph v -> [v]
successors v (Graph arcs labels styles) = arcs ! v

В документации оператора (!) Написано: «O (log n). Найдите значениена ключ. Вызывает ошибку, когда элемент не может быть найден. "

Я хочу вернуть пустой список [], когда элемент не может быть найден

Как мне справиться с этим? Большое спасибо.

1 Ответ

3 голосов
/ 06 октября 2019

Здесь вы можете использовать оператор !? (Ord k => Map k a -> k -> Maybe a) . Это вернет Nothing в случае, если ключ не существует, и Just v с v значением в случае, если оно существует, как указано в документации:

O (log n) . Найдите значение по ключу. Возвращает Nothing, когда элемент не может быть найден .

Тогда нам все еще нужно преобразовать это в пустой список. Для этого мы можем использовать fromMaybe :: a -> Maybe a -> a, здесь мы сначала даем значение «по умолчанию» для использования в случае Nothing, а затем передаем ему Maybe a. Если это Nothing, мы используем значение по умолчанию, если это Just v, он вернет v:

import Data.Map (Map,empty,member,insert,keys,<b>(!?)</b>)
import Data.Maybe(<b>fromMaybe</b>)

successors :: Ord v => v -> Graph v -> [v]
successors v (Graph arcs _ _) = fromMaybe [] (arcs <b>!?</b> v)

или как @ Берги говорит мы можем использовать findWithDefault :: Ord k => a -> k -> Map k a -> a:

import Data.Map (Map,empty,member,insert,keys,<b>findWithDefault</b>)
import Data.Maybe(fromMaybe)

successors :: Ord v => v -> Graph v -> [v]
successors v (Graph arcs _ _) = <b>findWithDefault</b> [] v arcs
...