#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 .