为什么第二种拉链类型是数据列表而不是纯数据?

时间:2019-06-18 16:03:14

标签: haskell zipper

我通过Learn your Haskell上的教程获得了成功 我问自己为什么作者使用列表作为已实现的拉链的第二种类型?

以下是相关代码:

func GetKeys(filename string) {
    var record []string
    var err error
    file, err := os.Open(filename)
    if err != nil {
        log.Fatal(err)
    }
    defer file.Close()
    // Create a new reader.
    reader := csv.NewReader(bufio.NewReader(file))
    for {
        record, err = reader.Read()
        // Stop at EOF.
        if err == io.EOF {
            break
        }
        fmt.Printf("%v", record) // works fine
        fmt.Printf("%v\n", record[0]) // works fine too
    }
    fmt.Printf("%v\n", record) // returns empty slice
}

func main() {
    GetKeys("credentials.csv")
}

您可以使用的命令:

type Name = String
type Data = String
data FSItem = File Name Data
    | Folder Name [FSItem]
    deriving (Show)

data FSCrumb = FSCrumb Name [FSItem] [FSItem]
    deriving (Show)
type FSZipper = (FSItem, [FSCrumb])

-- -------------------------------------------------------------------------------
-- Some other code he uses
-- -------------------------------------------------------------------------------

fsUp :: FSZipper -> FSZipper
fsUp (item, FSCrumb name ls rs : bs) = (Folder name (ls ++ [item] ++ rs), bs)

fsTo :: Name -> FSZipper -> FSZipper
fsTo name (Folder folderName items, bs) =
    let (ls, item:rs) = break (nameIs name) items
    in  (item, FSCrumb folderName ls rs:bs)

nameIs :: Name -> FSItem -> Bool
nameIs name (Folder folderName _) = name == folderName
nameIs name (File   fileName   _) = name == fileName

x -: f = f x

-- -------------------------------------------------------------------------------
-- Example to work on
-- -------------------------------------------------------------------------------

myDisk :: FSItem  
myDisk = 
    Folder "root"   
        [ File "goat_yelling_like_man.wmv" "baaaaaa"  
        , File "pope_time.avi" "god bless"  
        , Folder "pics"  
            [ File "ape_throwing_up.jpg" "bleargh"  
            , File "watermelon_smash.gif" "smash!!"  
            , File "skull_man(scary).bmp" "Yikes!"  
            ]  
        , File "dijon_poupon.doc" "best mustard"  
        , Folder "programs"  
            [ File "fartwizard.exe" "10gotofart"  
            , File "owl_bandit.dmg" "mov eax, h00t"  
            , File "not_a_virus.exe" "really not a virus"  
            , Folder "source code"  
                [ File "best_hs_prog.hs" "main = print (fix error)"  
                , File "random.hs" "main = print 4"  
                ]  
            ]  
        ] 

无论我做什么,我总是得到一个只有一个项目的列表,所以只使用*Filesystem> let newFocus1 = (myDisk,[]) -: fsTo "programs" -: fsTo "source code" *Filesystem> let newFocus2 = (myDisk,[]) -: fsTo "pics" -: fsTo "ape_throwing_up.jpg" 而不是FSCrumb会更好吗?

1 个答案:

答案 0 :(得分:1)

问题很简单,就是用来获取面包屑数量的方法。 一种简单(正确)的方法是:

numberOfBreadcrumbs :: FSZipper -> Int
numberOfBreadcrumbs (_, breadcrumbs) = length breadcrumbs