我刚刚开始学习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) && loc <= (x+width, y+height) then Just node else Nothing
findNode loc node@(Node (x, y) (width, height) children) =
if loc >= (x, y) && 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?
。
答案 0 :(得分:6)
那是因为您的nodes
类型为[Maybe Node]
。您可以通过明确地对其进行批注并再次编译来验证它:
findNode loc node@(Node (x, y) (width, height) children) =
if loc >= (x, y) && 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
的类型为[Maybe Node]
。 (一般地图类型为map :: (a -> b) -> [a] -> [b]
,在您的情况下,findNode loc
的类型为Node -> Maybe Node
,因此结果类型为[Maybe Node
])。 dropWhile
的类型为(a -> Bool) -> [a] -> [a]
。在您的情况下,a
已经Maybe Node
,因此您的nodes
类型为[Maybe Node]
。