2013-05-07 3 views
1

Я хочу написать функцию treeFold, которая принимает: Функция f типа 'a -> b -> a, Значение x типа a, A Дерево b с именем t и возвращает значение типа a. Возвращаемое значение вычисляется путем выполнения обхода дерева в порядке, проходящего через частичные результаты через x. Вот мой код:У меня ошибка при запуске функции foldTree

import Control.Exception 
import Control.Monad 
import Control.DeepSeq 
import qualified Data.List as List 
import Test.HUnit 

data Tree a = Empty 
      | Node a (Tree a) (Tree a) 
      deriving (Show, Eq) 



insertTree :: (Ord a, Show a) => Tree a -> a -> Tree a 
insertTree Empty x = Node x Empty Empty 
insertTree (Node v tLeft tRight) x 
    | x == v = Node v tLeft tRight 
    | x < v = Node v (insertTree tLeft x) tRight 
    | x > v = Node v tLeft (insertTree tRight x) 


createTree :: (Ord a, Show a) => [ a ] -> Tree a 
createTree = foldl insertTree Empty 

intTree = createTree [9, 7, 2, 8, 6, 0, 5, 3, 1]

listTree = createTree (List.permutations [ 0 .. 3 ]) 

strTree = createTree [ "hello" 
        , "world" 
        , "lorem" 
        , "ipsum" 
        , "dolor" 
        , "sit" 
        , "amet" 
        ] 
treeFold :: (a -> b -> b -> b) -> b -> Tree a -> b 
treeFold f z Empty = z 
treeFold f z (Node v l r) = f v (subfold l) (subfold r) 
    where subfold = foldTree f z 

Но когда я запустить код, я получил сообщение «Не удалось совместить ошибку типа». Мне было интересно, как я могу исправить эту проблему? для exmaple: Main> treeFold (+) 10 intTree, вместо того, чтобы получать Main> 51, я получил ошибку соответствия типа. Любая помощь приветствуется.

+0

Посмотрите на тип первого аргумента, что 'treeFold' ожидает:' А -> В -> B -> b'. Теперь рассмотрим тип '(+)': '(Num a) => a -> a -> a'. Они не совпадают. Вам нужно предоставить функцию из трех аргументов, но '(+)' принимает только два аргумента. –

+0

здесь фиксированный код treeFold: treeFold :: (a -> b -> a) -> a -> Дерево b -> a treeFold fz Пусто = z treeFold fz (Node lxr) = \t treeFold f (fx (treeFold fzr)) l ... Но до получения ошибки sam e. – user2210328

+0

Ваш оригинальный код 'treeFold' был верным. Ошибка заключалась в том, что вы предоставили ей '(+)' в качестве аргумента. Вам нужно указать что-то другое, кроме '(+)' 'treeFold'. –

ответ

1

В функции

treeFold :: (a -> b -> b -> b) -> b -> Tree a -> b 
treeFold f z Empty = z 
treeFold f z (Node v l r) = f v (subfold l) (subfold r) 
    where subfold = foldTree f z 

вы используете f на три значения: v, (subfold l) и (subfold r). Вот почему ваша подпись типа требует f, чтобы принять три аргумента.

Мне кажется, что вы бы лучше применяя двухаргументной f дважды, один раз, чтобы объединить v и (subfold l), другой, чтобы объединить, что с (subfold r):

treeFold f z Empty = z 
treeFold f z (Node v l r) = f (f v (subfold l)) (subfold r) 
    where subfold = treeFold f z 

Это означает, что если принимаем f :: a -> b -> c, затем subfold l :: b по причине f v (subfold l), но также subfold l :: c т.к. возвращенние из treeFold. Таким образом, c и b являются одинаковыми (c ~ b) и f v (subfold l) :: b. Это используется как первый аргумент первого f, поэтому a ~ b тоже. Таким образом, для этого нового использования-F-два раза версии,

treeFold :: (b -> b -> b) -> b -> Tree b -> b 
Смежные вопросы