2011-07-10 15 views
7

Witam Haskellers i Haskellettes,Haskell - zagnieżdżone pustych list

podczas czytania http://learnyouahaskell.com/ mój przyjaciel wpadł na pewien problem:

jest to możliwe w Haskell napisać rekurencyjną funkcję, która daje True jeśli wszystkie sub -sub -_- podlisty są puste. Moje pierwsze przypuszczenie było - powinno być - ale mam duży problem po prostu przy pisaniu adnotacji typu.

próbował coś podobnego

nullRec l = if null l 
       then True 
       else if [] `elem` l 
        then nullRec (head [l]) && nullRec (tail l) 
        else False 

jest - nie działa - :-)

wymyśliłem coś jak

  • składanym z concat - aby uzyskać aa pojedynczą długą listę
    (daje mi problemy z implementacją)
  • lub tworzenie nieskończonej, treelopodowej postaci danych - i czyni to z listy
    (jeszcze nie zaimplementowane)

ale ten brzmi trochę jak overkill dla tego problemu. co jest Twoje pomysły - na słoneczną niedzielę like this ;-)

Dzięki z góry


jako reakcja na wszystkich komentarzy - to jest zły styl bym chciał dodać to po prostu eksperyment !
NIE próbuj tego w domu! ;-)

+3

Zastanów się, jaki powinien być typ takiej funkcji (jeśli ją wdrożysz na zwykłych listach)! – yatima2975

+0

myślałem o tym - powinno to być nieskończone [[... [a] ...]], ale nie da się tego zapisać w haskell - dlatego wymyśliłem drugie podejście. Ale czy jest łatwiejszy sposób na zrobienie tego. Dodatkowo mój mózg jest nieco powolny, ponieważ dzisiaj jestem chory. – epsilonhalbe

+2

Chory, czy nie, jesteś na dobrej drodze! Łatwo jest napisać rodzinę funkcji 'nullRec2 :: [[a]] -> Bool',' nullRec3 :: [[[a]]] -> Bool' i tak dalej (spróbuj parę!), Ale ty nie można łatwo dopasować do podpisu jednego typu. Potrzebny jest typ drzewa, taki jak "drzewo danych a = gałąź [drzewo a] | Węzeł a' lub może jest coś możliwego z typeclasses (jeszcze nie myślałem o tym podejściu). – yatima2975

Odpowiedz

5

Co powiesz na typografię?

{-# LANGUAGE FlexibleInstances, OverlappingInstances #-} 

class NullRec a where 
    nullRec :: a -> Bool 

instance NullRec a => NullRec [a] where 
    nullRec [] = True 
    nullRec ls = all nullRec ls 

instance NullRec a where 
    nullRec _ = False 

main = print . nullRec $ ([[[[()]]]] :: [[[[()]]]]) 
+5

Dokładniej, używasz nie tylko klasy typu, ale także rozszerzenia GHC [OverlappingInstances] (http://www.haskell.org/ghc/docs/7.0.4/html/users_guide/type-class-extensions.html # overlap instancji). Bez tego rozszerzenia nawet użycie klasy typu nie może osiągnąć tego, co jest wymagane w pytaniu. Sugeruje to, że jeśli ktokolwiek ma to zaimplementować (poza eksperymentem), program prawdopodobnie nie został zaprojektowany we właściwy sposób. –

4

Nie jest to możliwe przy użyciu tylko polimorfizmu parametrycznego, z uwagi na następujące.

Rozważmy następujące wartości:

x = [8] :: [Int] 
y = [3.0] :: [Double] 
z = [[]] :: [[Int]] 

Oczywiście chcesz, aby funkcja działała zarówno x i y, zatem jego typ musi być null1 :: [a] -> Bool. (Czy ktoś może mi pomóc uczynić ten argument wyglądać formalny? W jaki sposób można pokazać, że jest to wyjątkowy najbardziej specyficzny kontekst mniej typ unifikowalny z [Int] -> Bool i [Double] -> Bool? Czy jest nazwa dla tej relacji między typami?)

teraz , jeśli masz ten typ, to null1 z będzie równe null1 x, ponieważ różnią się one tylko wartościami elementów listy, z których są pobierane. (nawet nie blisko formalnego dowodu znowu :()

Co chcesz za z jest null2 :: [[a]] -> Bool, które różnią się w zachowaniu, a tym samym dając null1 i null2 sama nazwa będzie wymagać przeciążenia.(patrz odpowiedź FUZxxl)

+0

Uważam ten argument za dość przekonujący. – luqui

+0

Mam ochotę 'null1. (: []) :: a -> Bool' przybliża nas do formalnego dowodu, ale wciąż nie wiem jak zrobić ostatni krok (pokazując, że 'a -> Bool' jest tym samym co' Bool'). – Rotsor

+0

Jest to rodzaj swobodnego twierdzenia odwrotnego, ale największa niższa granica "Int" i "Podwójnego" (na siatce typów bez kontekstu Haskella, z podstawieniem jako relacją) to "a", ponieważ nie można zastępuj zmienne typu w obu (nie ma żadnych!) i kończą na tym samym typie. A może zmieniam kierunek jazdy w górę i w dół? – yatima2975

Powiązane problemy