简体   繁体   中英

Haskell data structure find method

As I'm constructing my data structure I found an issue that I'm having trouble solving it. My data structure "Structure" is String and a list of subStructures.

The issue is in the "lookFor" method below, that is supposed to look for a subStructure named "a" in (Structure b xs) and return it. If not on "b"'s list (xs), it should continue looking in each xs element's list and so on. If not found it should do nothing.

My idea was recursion, and for that, I thought "map lookFor xs" in case it hasn't found the Structure named "a".

Ghci says "Couldn't match expected type Structure with actual type [Structure]" Wich I understand, because after all map returns a list of elements and not an element.

data Structure = Structure String [Structure]

name :: Structure -> String
name (Structure a xs) = a

subStrcts :: Structure -> [String]
subStrcts (Structure a []) = []
subStrcts (Structure a xs) = [name x | x <- xs]

lookFor :: String -> Structure -> Structure
lookFor a (Structure b xs) 
    | elem (elemIndex a (subStrcts (Structure b xs))) [0..] = xs !! (fromJust (elemIndex a (subStrcts (Structure b xs))))
    | otherwise = map (lookFor a) xs

Any ideas? Thanks

A possible solution is:

import Control.Applicative
import Data.Foldable

data Structure = Structure String [Structure]
               deriving Show

lookFor :: String -> Structure -> Maybe Structure
lookFor a s@(Structure b xs)
   | a == b    = Just s
   | otherwise = asum (map (lookFor a) xs)

Above, map (lookFor a) xs searches a in the substructures. This produces a [Maybe Structure] , on which we use asum to take the first Just _ value, so that we can return it. (If no such value is found, asum returns Nothing .)

If you don't want to exploit asum from the libraries, defining it is a nice beginner exercise.

As a recursive structure, you need to set a base case. In your example, this happens when you have exhausted all structures in your list.

As @WillemVanOnsem, it's better to return a Maybe Structure , as it is possible for the lookFor function not to find the Structure

import Data.List (elemIndex)
import Data.Maybe (fromJust, isJust)

data Structure = Structure String [Structure]

name :: Structure -> String
name (Structure a xs) = a

subStrcts :: Structure -> [String]
subStrcts (Structure a []) = []
subStrcts (Structure a xs) = [name x | x <- xs]

lookFor :: String -> Structure -> Maybe Structure
lookFor a (Structure b xs) 
    | null xs = Nothing
    | isJust maybeIndex = fmap (xs !!) maybeIndex
    | otherwise = lookFor a (Structure (name (head xs)) (tail xs))
    where maybeIndex = elemIndex a (subStrcts (Structure b xs))

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM