0

文字列リストからランダムなアイテムを取得して別の文字列リストに保存しようとしていますが、コードを機能させることができません。

    import System.Random
    import Control.Applicative ( (<$>) )

    food = ["meatballs and potoes","veggisoup","lasagna","pasta bolognese","steak and fries","salad","roasted chicken"]
    
    
    randomFood xs = do
              if (length xs - 1 ) > 0 then 
                 [list] <- (fmap (xs!!) $ randomRIO (0, length xs -1))
                 else
                 putStrLn (show([list])

入力'<-'で解析エラーが発生しますが、それ以上の問題があると確信しています。また、リストに同じ料理が2日続けて含まれている可能性があるという問題もあります。これは私が望むものではなく、重複を削除できると思いますが、リスト内の同じままにしておきたいアイテムの数も削除されます。リスト内の番号として。

誰かが私がこれをどのように解決できるか良い考えを持っていますか?私は今一日を探していて、私にとって有用なものを見つけることができませんが、それは私が間違った場所を探しているからです。私がこれを行う方法や情報を見つけることができる場所についての提案は大歓迎です!

4

2 に答える 2

5

それが機能しなかった理由は、あなたの後に別の ものが必要だったからです。(後は、ではなく式が必要です。)doif...thenthenpattern <- expression

randomFood :: String -> IO ()  -- type signature: take a String and do some IO.
randomFood xs = do
          if length xs > 1 then do
             [list] <- (fmap (xs!!) $ randomRIO (0, length xs -1))
             else
             putStrLn (show([list])

しかし、実際にはリストに対して何もしないため、それでもコンパイルされません。すべてのブロックの終わりに、do戻るための式が必要です。xsの長さが短すぎる場合でも、いくつかのものを印刷するつもりだったと思います。選択する食べ物が複数ある場合は、選択した食べ物を印刷するつもりだったと思います。

より良いでしょう:

randomFood :: String -> IO () 
randomFood xs | length xs <= 1 = putStrLn $ show xs
randomFood xs | otherwise = do
             item <- (xs!!) <$> randomRIO (0, length xs -1)
             putStrLn $ show(item)

この| boolean test =構文は、入力に基づく条件付き回答に適しています。

アイテムのリストではなく、ランダムに1つのアイテムを選択しているため、に変更[list]しました。Haskellは、1文字の文字列が一致するため、itemを入れてくれてとてもうれしいです。たとえば、「h」は。の略であるため、。それより長い文字列はあなたに与えます。特に、指定したすべての食品には複数の文字が含まれているため、この定義では機能しません。あなたの表現によって返されるものと一致するので、それは問題ありません。[list][list]"h" = [list]list='h'['h']Pattern match failurerandomFooditemrandomRIO

インポート<$>して使用しませんでしたが、優れた演算子なので、に置き換えfmap f iothingましたf <$> iothing

私はついに、短いリストで間違ったことをしていることに気づきました。私がそうするならば、randomFood ["lump of cheese"]私は得るでしょう、それは私に与えるもの["lump of cheese"]と矛盾しています。短いリストを空のリストから分離する必要があると思います。これにより、パターンマッチングを増やし、ブール値を減らすことができます。randomFood ["lump of cheese"]"lump of cheese"

randomFood :: String -> IO () 
randomFood []        = putStrLn "--No food listed, sorry.--"
randomFood [oneitem] = putStrLn . show $ oneitem 
randomFood xs = do
         item <- (xs!!) <$> randomRIO (0, length xs -1)
         putStrLn . show $ item

randomFoodこれにより、入力がどのように見えるかに応じて3つの異なる定義が与えられます。

putStrLn (show (item))ここでは、 -に置き換えました。putStrLn . show $ item関数showを作成し、それputStrLnをに適用します($item

于 2012-09-19T19:11:39.847 に答える
2

注意すべきいくつかのポイント:

  • 純粋なコードと不純なコードを混在させないでください。
  • すでに書かれていることを繰り返すのではなく、タスクにライブラリを使用するようにしてください。

これがrandom-fuライブラリを使用したコードです

import Data.Random
import Control.Applicative

food :: [String]
food = ["meatballs and potoes","veggisoup","lasagna","pasta bolognese","steak and fries","salad","roasted chicken"]

randomFood :: [String] -> RVar (Maybe String)
randomFood [] = return Nothing
randomFood xs = Just <$> randomElement xs

main :: IO ()
main = (sample $ randomFood food) >>= print

これは、リストからランダムに1つの要素を選択するようなものです。

> main 
Just "steak and fries"
> main 
Just "meatballs and potoes"

上記のリストのランダムな順列だけを出力したい場合は、次のように使用できますshuffle

main = (sample $ shuffle food) >>= print

 > main 
 ["meatballs and potoes","lasagna","steak and fries","roasted chicken","salad","pasta bolognese","veggisoup"]
 > main 
 ["roasted chicken","veggisoup","pasta bolognese","lasagna","steak and fries","meatballs and potoes","salad"]
于 2012-09-19T22:27:39.597 に答える