Рекурсия, возвращающая список списка, используя haskell - PullRequest
1 голос
/ 21 сентября 2019

Я довольно новичок в Haskell, и я не уверен, как решить / подойти к этой проблеме: я хочу функцию с сигнатурой типа: [((Double, Double), Bool)] -> [[(Double, Double)]].Функция должна добавлять (Double, Double) в список списков, только если Bool == True.Если bool имеет значение False, я хочу, чтобы (Double, Double), связанный со следующим True bool, был добавлен в новый список.Последовательные (Double, Double) в паре с Bool == True должны быть добавлены в тот же список.Например, ввод: [((1,1),True),((2,2), False),((3,3), False),((4,4),True),((5,5),True)] должен возвращать [[(1,1)],[(4,4),(5,5)]].Я провел небольшое исследование, и кажется, что функция groupBy может быть полезна для решения проблемы, но я не совсем уверен, как правильно ее использовать.Поскольку я новичок в Haskell, я бы предпочел более простое решение или объяснение, но любые предложения помогут.

Пока мой код просто создает новый список для каждого (Double, Double), связанного с True bool.Я не совсем уверен, как добавить существующий список в список.

consecTrue :: [((Double, Double),Bool)] -> [[(Double,Double)]]
consecTrue xs = case xs of
    [] -> []
    x:xs
        |snd x == True -> [fst x]:consecTrue xs
        |snd x == False -> consecTrue xs

Ответы [ 2 ]

1 голос
/ 21 сентября 2019

Да, groupBy можно использовать.Вам понадобится функция сравнения для подачи groupBy, назовем ее grf.Самый простой путь - это, вероятно, постепенное тестирование решения в интерактивной команде: ghci.

$ ghci
Prelude> 
Prelude Data.List> import Data.List
Prelude Data.List> grf ((x1,y1),p1) ((x2,y2),p2) = (p1==p2)
Prelude Data.List> let lsa = [((1,1),True),((2,2), False),((3,3), False), ((4,4),True),((5,5),True)]
Prelude Data.List> 
Prelude Data.List> lsb = groupBy grf lsa
Prelude Data.List> lsb
[[((1,1),True)],[((2,2),False),((3,3),False)],[((4,4),True),((5,5),True)]]
Prelude Data.List> 


Это только начало.Затем нужно избавиться от ложных, а затем избавиться от самих логических значений.

Prelude Data.List> 
Prelude Data.List> lsc = filter (snd . head) lsb
Prelude Data.List> lsc
[[((1,1),True)],[((4,4),True),((5,5),True)]]
Prelude Data.List> 
Prelude Data.List> lsd = map (map fst) lsc
Prelude Data.List> lsd
[[(1,1)],[(4,4),(5,5)]]
Prelude Data.List> 
Prelude Data.List> 

Собираем все воедино:

import Data.List

consecTrue :: [((Double, Double),Bool)] -> [[(Double,Double)]]
consecTrue xs = let grf ((x1,y1),p1) ((x2,y2),p2) = (p1==p2)
                in  map (map fst) (filter (snd . head) (groupBy grf xs))

main = do
    let lsa = [((1,1),True),((2,2), False),((3,3), False),
              ((4,4),True),((5,5),True)]
    let res = consecTrue lsa

    putStrLn $ "input  = " ++ show lsa
    putStrLn $ "output = " ++ show res

Кажется, это делает то, что вы хотели:

input  = [((1.0,1.0),True),((2.0,2.0),False),((3.0,3.0),False),((4.0,4.0),True),((5.0,5.0),True)]
output = [[(1.0,1.0)],[(4.0,4.0),(5.0,5.0)]]
0 голосов
/ 22 сентября 2019

Как новичок, изучающий Haskell, даже не зная, что такое map, имеет смысл просить сделать это в первую очередь с помощью простой прямой рекурсии, создавая определение, которое стоит само по себе, не используялюбые библиотечные функции.

И определение с помощью простой прямой рекурсии - это просто перечисление возможных случаев, с которыми мы представляем:

consecTrue :: [(t, Bool)] -> [[t]]
  -- empty list:
consecTrue [] = []
  -- list with exactly one entry in it:
consecTrue [(a,True)] = [[a]]
consecTrue [(a,False)] = []
  -- list with two or more entries in it:
consecTrue ((a1,True) : (a2, True) : more2)  =  (a1:r):q  where  
                                                    (r:q) = consecTrue ((a2,t2) : more2)
consecTrue ((a1,True) : (a2,False) : more2)  =  [a1] : consecTrue more2
consecTrue ((a1,False) : more1)              =  consecTrue more1

(Double, Double) - несущественная, посторонняя деталь.Достаточно просто t, что означает, что туда может пойти все что угодно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...