Попытка перебрать лесную ошибку на Haskell
Я пытаюсь назначить каждому узлу леса номер, чтобы не было двух узлов с одинаковым номером. Я пытаюсь использовать 2 функции, которые вызывают друг друга рекурсивно, но я получаю некоторые ошибки компиляции. Вот код:
numberTree :: Int -> Tree a -> (Tree Int,Int)
numberTree n (Node c []) = (Node n [], n+1)
numberTree n (Node _ (x:xs)) = (Node n fst.numberForest (n+1) xs, snd.numberForest (n+1) xs)
numberForest :: Int -> [Tree a] -> ([Tree Int],Int)
numberForest n (x:xs) = ((fst(numberTree n x )):(fst(numberForest (n+1) xs)), snd(numberForest (n+1) xs)+1)
numberForest n (x:xs) = ((fst(numberTree n x )):(fst(numberForest (n+1) xs)), snd(numberForest (n+1) xs)+1)
Я получаю следующие ошибки:
.hs: 27: 34: не удалось найти ожидаемый тип
b0 -> c0' with actual type
Tree Int Возможная причина:Node' is applied to too many arguments In the first argument of
(.) ', а именно `Node n fst' В выражении: Node n fst . numberForest (n + 1) xs
.hs:27:34:
Couldn't match expected type `Tree Int' with actual type `a0 -> c0
In the expression: Node n fst . numberForest (n + 1) xs
In the expression:
(Node n fst . numberForest (n + 1) xs,
snd . numberForest (n + 1) xs)
In an equation for `numberTree':
numberTree n (Node _ (x : xs))
= (Node n fst . numberForest (n + 1) xs,
snd . numberForest (n + 1) xs)
.hs:27:42:
Couldn't match type `(a1, b1) -> a1' with `[Tree Int]'
Expected type: Forest Int
Actual type: (a1, b1) -> a1
Probable cause: `fst' is applied to too few arguments
In the second argument of `Node', namely `fst'
In the first argument of `(.)', namely `Node n fst'
.hs:27:46:
Couldn't match expected type `a0 -> b0'
with actual type `([Tree Int], Int)'
Possible cause: `numberForest' is applied to too many arguments
In the second argument of `(.)', namely `numberForest (n + 1) xs'
In the expression: Node n fst . numberForest (n + 1) xs
.hs:27:70:
Couldn't match expected type `Int' with actual type `a2 -> c1'
In the expression: snd . numberForest (n + 1) xs
In the expression:
(Node n fst . numberForest (n + 1) xs,
snd . numberForest (n + 1) xs)
In an equation for `numberTree':
numberTree n (Node _ (x : xs))
= (Node n fst . numberForest (n + 1) xs,
snd . numberForest (n + 1) xs)
.hs:27:74:
Couldn't match expected type `a2 -> (a3, c1)'
with actual type `([Tree Int], Int)'
Possible cause: `numberForest' is applied to too many arguments
In the second argument of `(.)', namely `numberForest (n + 1) xs'
In the expression: snd . numberForest (n + 1) xs
Что не так и как мне это решить?
2 ответа
Эта линия
numberTree n (Node _ (x:xs)) = (Node n fst.numberForest (n+1) xs, snd.numberForest (n+1) xs)
на самом деле означает
numberTree n (Node _ (x:xs)) = ( (Node n fst) . (numberForest (n+1) xs)
, snd . (numberForest (n+1) xs))
который пытается составлять деревья вместо функций, заставляя компилятор жаловаться. Вы, вероятно, хотите что-то вроде этого:
numberTree n (Node _ (x:xs)) = ( Node n (fst (numberForest (n+1) xs))
, snd (numberForest (n+1) xs))
Тем не менее, будьте осторожны, что код выше вычисляет numberForest (n+1) xs
дважды, вызывая экспоненциальный взрыв. Вы можете избежать этого, например, используя let ... in ...
следующее
numberTree n (Node _ (x:xs)) = let result = numberForest (n+1) xs
in (Node n (fst result), snd result)
Вы можете улучшить это, используя сопоставление с образцом внутри let
:
numberTree n (Node _ (x:xs)) = let (forest, n') = numberForest (n+1) xs
in (Node n forest, n')
Государственная монада - твой друг.
import Control.Monad.Trans.State
data Tree a = Node a (Forest a)
type Forest a = [Tree a]
numberTreeS :: Tree a -> State Int (Tree Int)
numberTreeS (Node _ xs) = do
n <- get
put (n + 1)
xs' <- numberForestS xs
return $ Node n xs'
numberForestS :: Forest a -> State Int (Forest Int)
numberForestS = mapM numberTreeS
numberForest :: Forest a -> Forest Int
numberForest xs = evalState (numberForestS xs) 0
Это более читабельно, чем явная передача состояний.