2012-05-04 3 views
1

я следующее:Haskell алгебраического типа данных шаблону

data Alpha a = Beta a [Alpha a] 
val = Beta 1 [Beta 2 [], Beta 5 [Beta 7 []]] 

Я пытаюсь определить функцию, которая будет двигаться над Вэлом типа Альфа Int и просуммировать. Мой желаемый подход, чтобы извлечь все Ints, а затем суммировать получившийся список, но я изо всех сил, чтобы извлечь все Ints, как я не знаю, что делать с рекурсией ...

небольшая попытка:

checkAlpha :: Alpha Int -> [Int] 
checkAlpha (Beta a []) = [a] 
checkAlpha (Beta a b) = [a] ++ (map checkAlpha b) 

Очевидно, что это не совсем работает, но я не вижу решения в поле зрения.

+1

В функции 'b' имеет тип' [Альфа Int] '. Отображение 'checkAlpha' над этим списком дает вам' [[Int]] ', но ваша подпись говорит, что вы хотите вернуть' [Int] '. Вот почему вам нужно «свернуть» список в один слой - то есть '(concat.). map' также известен как 'concatMap'. – Vitus

+0

минимальное исправление заключается в том, чтобы вставить 'concat $' между '(' и 'map checkAlpha b)' в ваш код, чтобы свести на один уровень список списков. Затем вы замечаете, что первое предложение является экземпляром второго, потому что 'map _ [] === []'. Затем вы заменяете '[a] ++' 'на' a: ', чтобы прийти к решению Даниэля. Таким образом, вы были очень близки. :) –

ответ

7

Если вы использовали

concatMap :: (a -> [b]) -> [a] -> [b] 

вместо map, он будет работать и быть достаточно элегантно.

Вам не нужно рассматривать случай пустой список в качестве второго компонента специально,

checkAlpha :: Alpha a -> [a] 
checkAlpha (Beta a alphas) = a : concatMap checkAlpha alphas 

делает то, что вы хотите, и не зависит от типа параметра.

0

Вы могли бы рассмотреть возможность использования Tree вместо Alpha, который имеет много удобных операций:

> flatten $ Node 1 [Node 2 [], Node 5 [Node 7 []]] 
[1,2,5,7] 
Смежные вопросы