2017-05-21 10 views
4

これは説明するのが少し難しいですが、私はこの状況に数回ぶつかりました。パラメータの型が静的でない場合、どのようにHaskellステートメントを分割できますか?

work :: String -> IO() 
work a = do 
    input <- lines <$> getContents 
    sortF <- let f = flip sortByM input 
    in case a of 
     "name" -> f (return . id   :: FilePath -> IO FilePath) 
     "time" -> f (getModificationTime :: FilePath -> IO UTCTime) 
     _ ->  f (getModificationTime :: FilePath -> IO UTCTime) 
    print sortF 

sortByM :: (Monad m, Ord a) => (b-> m a) -> [b] -> m [b] 
sortByM f x = do 
    x' <- mapM f x 
    return $ fst <$> (sortBy (comparing snd) $ zip x x') 

を上記のエラーがスローされます:

コードは次のようである理にかなって

• Couldn't match type ‘UTCTime’ with ‘[Char]’ 
    Expected type: String -> IO FilePath 
    Actual type: FilePath -> IO UTCTime 
• In the first argument of ‘f’, namely 
    ‘(getModificationTime :: FilePath -> IO UTCTime)’ 
    In the expression: 
    f (getModificationTime :: FilePath -> IO UTCTime) 
    In a case alternative: 
     "time" -> f (getModificationTime :: FilePath -> IO UTCTime) 

を、何とか上記目的を達成する方法はありますか?そうでなければ、私はあまり、保守感じる、下記行う必要があります:

work :: String -> IO() 
work a = do 
    input <- lines <$> getContents 
    sortF <- case a of 
     "name" -> flip sortByM input (return . id   :: FilePath -> IO FilePath) 
     "time" -> flip sortByM input (getModificationTime :: FilePath -> IO UTCTime) 
     _ ->  flip sortByM input (getModificationTime :: FilePath -> IO UTCTime) 
    print sortF 

sortByM :: (Monad m, Ord a) => (b-> m a) -> [b] -> m [b] 
sortByM f x = do 
    x' <- mapM f x 
    return $ fst <$> (sortBy (comparing snd) $ zip x x') 
+0

は 'せ、F X = sortByM X input'仕事をしていますか? – melpomene

答えて

6

Dreaded Monomorphism Restrictionに感染しています。最適化とコード生成に関する問題のため、GHCが明示的な引数を持たない値を見ると、予想されるより一般的な多態型ではなく、単相型を推論します。あなたはNoMonomorphismRestrictionプラグマを使用して制限を無効にするか、またはあなたがfに明示的なパラメータ与えることができます

sortF <- let f xs = sortByM xs input in ... 
+0

'f'にタイプシグネチャを付けるだけでいいのですか? –

+0

それはうまくいくかもしれませんが、(私は自分自身をほとんど理解していないので)入りたくない型変数のスコープ規則に絡み合うことも意味します。この場合、問題はありませんが、最上位レベルの関数が多相であり、それらの変数を "f"の型で使用したい場合には、毛がかってしまいます。 –

+0

'ScopedTypeVariables'は言語の一部であったはずです... –

1

はあなたが望むものについていくつかの仮定を作る...コード構造上の多くのオプションがあるように傾向があります。あなたは和タイプ(ここではない素晴らしいソリューション)を持つことができます。sortFはそれがShowのインスタンスであるということであるあなただけshowを呼び出すことができる「マルチ型付け」についてあなたは本当に知っている唯一の事ので

... 
    sortF <- let f = flip sortByM input 
    in case a of 
     "name" -> Left <$> f (return . id   :: FilePath -> IO FilePath) 
     "time" -> Right <$> f (getModificationTime :: FilePath -> IO UTCTime) 
     _ ->  Right <$> f (getModificationTime :: FilePath -> IO UTCTime) 
    either print print sortF 

をし、 Stringを使用します。

... 
    sortF <- let f = flip sortByM input 
    in show <$> case a of 
     "name" -> f (return . id   :: FilePath -> IO FilePath) 
     "time" -> f (getModificationTime :: FilePath -> IO UTCTime) 
     _ ->  f (getModificationTime :: FilePath -> IO UTCTime) 
    putStrLn sortF 

そして、あなたはStringにタイプを統一するとの組み合わせで、より機能指向のアプローチを使用することができます。

... 
    let op | a == "name" = return . show 
     | otherwise = fmap show . getModificationTime 
     f x = sortByM x input 
    putStrLn =<< f =<< op 
関連する問題