2013-03-12 36 views
1

我是一個Haskell noob,目前只能用它來配置xmonad。如何將Haskell System.Directory getHomeDirectory轉換爲常規字符串?

我想把我的配置放入一個git repo中,因爲我想不必硬編碼我的主目錄來獲取我的圖標。

我簽出 http://www.haskell.org/haskellwiki/How_to_get_rid_of_IO 但我太無知,無法理解它。

hd h = h =<< getHomeDirectory 

getIcon::String -> String 
getIcon out = ("^i("++hd++".xmonad/dzen2/"++out) 

這實際上可能嗎?如果是這樣,怎麼樣? 我不想在目錄上進行操作,我只是想將路徑作爲一個字符串來使用,並且會導致我死亡。

錯誤是:

Couldn't match expected type `[Char]' 
      with actual type `(FilePath -> IO b0) -> IO b0' 
In the first argument of `(++)', namely `hd' 
In the second argument of `(++)', namely 
    `hd ++ ".xmonad/dzen2/" ++ out' 
In the expression: ("^i(" ++ hd ++ ".xmonad/dzen2/" ++ out) 

在我看來就像是不會被刪除的IO單子都沒有。

更新: 好的。我將學習如何適應IO規則,直到那時我會保持硬編碼並用一個腳本來克隆配置文件,該腳本將替換適當的位。

回答

5

getIcon類型錯誤,因爲getHomeDirectory確實IO:

getIcon :: String -> IO String 
getIcon out = do 
    hd <- getHomeDirectory 
    return $ "^i(" ++ hd ++ ".xmonad/dzen2/" ++ out 

記住Haskell的區別是有副作用的代碼 - 通過類型IO - 比如讀硬盤。

所以調用者將是IO太:

main = do 
    s <- getIcon "foo" 
    .. now you have a regular string 's' ... 
+0

是的,我知道IO位,這是給我的麻煩。我需要返回的IO字符串作爲常規字符串,因爲這就是配置所期望的。不過,你的代碼確實幫助我理解了別的東西。做,並返回$ – Erius 2013-03-12 15:12:00

+3

@Erius沒有(安全)Haskell函數的類型'IO字符串 - >字符串'。 'IO'在'IO'中停滯了。 – 2013-03-12 15:50:07

1

你能在點更改代碼,在那裏你調用getIcon

如果你可以調用它之前獲得的主目錄,你可以做

getIcon :: String -> String -> String 
getIcon out hd = ("^i("++hd++".xmonad/dzen2/"++out) 

,然後無論你是從(假設它是在IO爲好)

someIOFunction = do 
    things 
    .... 
    hd <- getHomeDirectory 
    getIcon out hd 

只調用指出一個最後的手段,如果沒有其他的工作,有unsafePerformIO,但我從來沒有真的必須使用它(我覺得它通常是皺眉),所以我不能幫你太多。

+1

'unsafePerformIO'是一個非常特殊的用途的特殊工具,你不需要它(你會知道如果你需要它)。 – 2013-03-12 17:54:33

+0

好吧*我*不需要它......只是給予選擇。根據dons的編輯,我的回答已經很愚蠢。主要是我的時刻。 – tredontho 2013-03-12 18:40:22

1

你可以「爆發」其他monad,但你不能突破IO monad。像這樣的事情在你的Xmonad配置文件可能是你想要什麼:

getIcon::String -> String 
getIcon out = ("^i("++hd++".xmonad/dzen2/"++out) 

main = 
    h <- getHomeDirectory 
    let myIcon = getIcon "Firefox" 
    xmonad $ desktopConfig . . . -- use myIcon somewhere in this expression 
0

有可能在編譯時解開某些IO值,使用模板哈斯克爾。一個人的主目錄是一個合理的候選人,因爲它並不經常改變。用於獲取主目錄是在編譯時一個字符串模板Haskell的解決方案可能是編碼是這樣的:

{-# LANGUAGE TemplateHaskell #-} 
module HomeDirectory where 

import Language.Haskell.TH 
import System.Directory 

myHome :: String 
myHome = $(LitE . StringL `fmap` runIO getHomeDirectory) 

被警告,模板Haskell是出了名的棘手的野獸,雖然。這個例子很簡單,但它很容易導致複雜和混亂。

相關問題