Почему возвращаемое значение head неявно преобразуется в Maybe ?

#haskell

#haskell

Вопрос:

Я только начал изучать Haskell и для практики решил создать функцию, которая принимает дерево, элементы которого имеют позицию и размер, и возвращает элемент, расположенный в определенной позиции. Мой код выглядит так:

 import Data.List (dropWhile)

data Node = Node (Int,Int) (Int,Int) [Node] deriving(Eq, Show)

findNode :: (Int,Int) -> Node -> Maybe Node
findNode loc node@(Node (x, y) (width, height) []) = if loc >= (x, y) amp;amp; loc <= (x width, y height) then Just node else Nothing
findNode loc node@(Node (x, y) (width, height) children) = 
    if loc >= (x, y) amp;amp; loc <= (x width, y height)
        then if not $ null nodes then
            head nodes
        else
            Just node
    else Nothing
    where nodes = dropWhile (==Nothing) $ map (findNode loc) children
 

Насколько я могу судить, этот код компилируется и работает отлично, но мне любопытно одно: почему это head nodes приемлемо вместо Just $ head nodes? .

Ответ №1:

Это потому, что у вас nodes есть тип [Maybe Node] . Вы можете фактически проверить это, явно аннотировав его и скомпилировав его снова:

 findNode loc node@(Node (x, y) (width, height) children) = 
  if loc >= (x, y) amp;amp; loc <= (x width, y height)
  then
    if not $ null nodes
    then head nodes
    else Just node
  else Nothing
  where
    nodes = dropWhile (==Nothing) $ map (findNode loc) children :: [Maybe Node]
 

Так как же, nodes есть [Maybe Node] тип?

Тип map (findNode loc) children is [Maybe Node] . (Общий тип карты map :: (a -> b) -> [a] -> [b] — это, а в вашем случае тип findNode loc is Node -> Maybe Node и, следовательно, результирующий тип [Maybe Node ] ). И тип dropWhile is (a -> Bool) -> [a] -> [a] . В вашем случае a уже есть Maybe Node , и, следовательно, у вас nodes есть тип [Maybe Node] .

Комментарии:

1. @user467526 Возможно, вы захотите foldr (<¦>) Nothing $ map (findNode loc) children просто выбрать первое значение, не являющееся нулевым, в списке, если оно есть, и избавить себя от необходимости использовать оператор if и предложение where .