Haskell join getHomedirectory string -


i have file strings represent directories. of strings have tilde (~) in it. want join homedirectory (~) of user rest of string. have far:

import data.list (isprefixof) import system.directory (doesdirectoryexist, gethomedirectory) import system.filepath (joinpath)  getfullpath s     | "~" `isprefixof` s = joinpath [gethomedirectory, tail s]     | otherwise          = s 

but following error:

couldn't match type `io filepath' `[char]'expected type: filepath actual type: io filepathin expression: gethomedirectoryin first argument of `joinpath', namely `[gethomedirectory, tail s]'in expression: joinpath 

i don't know, , can't find, how convert types match , can joined together.

a more idiomatic solution @user2720372 suggests split non-monadic code monadic code. io actions monadic functions in io monad.

if need getfullpath locally makes sense cache home directory:

fullpath homepath s     | "~" `isprefixof` s = joinpath [homepath, tail s]     | otherwise          = s  main =     homepath <- gethomedirectory     let getfullpath = fullpath homepath     print $ getfullpath "~/foo" 

if still need full global getfullpath can implemented this:

getfullpath p =     homepath <- gethomedirectory     return $ fullpath homepath p 

and it's considered style keep fullpath , getfullpath separated.

also don't need isprefixof , tail in first place such simple case:

fullpath homepath ('~' : t) = joinpath [homepath, t] fullpath _ s = s 

if want monolithic getfullpath @user2720372's variant can simplified:

getfullpath s =     homedir <- gethomedirectory     return $ case s of         ('~' : t) -> joinpath [homedir, t]         _ -> s 

note code above refactorings of code preserving wrong behavior: should compare ~ first path component, not first path character. use splitpath system.filepath:

getfullpath s =     homedir <- gethomedirectory     return $ case splitpath s of         ("~" : t) -> joinpath $ homedir : t         _ -> s 

also, do-notation complicated cases. if use do-notation simple two-liners reducible application of fmap/<$>/>>=/>=>/liftm2 or other functions control.monad , control.applicative.

here version:

import control.applicative ((<$>)) import system.directory (gethomedirectory) import system.filepath (joinpath, splitpath)  getfullpath s = case splitpath s of     "~/" : t -> joinpath . (: t) <$> gethomedirectory      _ -> return s     main = getfullpath "~/foo" >>= print 

here yet more modular, less readable version:

import control.applicative ((<$>), (<*>)) import system.directory (gethomedirectory) import system.filepath (joinpath, splitpath)  main = getfullpath "~/foo" >>= print  withpathcomponents f = joinpath . f . splitpath   replacehome p ("~/" : t) = p : t replacehome _ s = s  getfullpath path = withpathcomponents . replacehome <$> gethomedirectory <*> return path      

haskell gurus invited rewrite preserve modularity improve readability :)


Comments

Popular posts from this blog

html - How to style widget with post count different than without post count -

How to remove text and logo OR add Overflow on Android ActionBar using AppCompat on API 8? -

javascript - storing input from prompt in array and displaying the array -