2016-09-18 3 views
0

Я хочу построить случайную строку, состоящую только из алфавитных символов. Это код, который я до сих пор:Изменение типов в Haskell

letters :: String 
letters = "abcdefghijklmnopqrstuvwxyz" 

{- | Generates any lower case alpha character. 
-} 
lowerAlpha :: Gen Char 
lowerAlpha = oneof (map return letters) 

getString :: Int -> String 
getString 0 = [] 
getString n = lowerAlpha : getString (n - 1) 

GetString передается случайный Int между 1 и 25. Поскольку lowerAlpha возвращает Gen Char GetString не будет работать, как он ожидает Чар, чтобы построить строку. Есть ли способ изменить строку Gen на строку? Это строка кода, где происходит проблема - getString n = lowerAlpha : getString (n - 1)

+0

Если вы могли бы сделать это [MCVE]. Это немного раздражает, когда нам нужно угадать, что такое «Gen» и «oneof». – leftaroundabout

+1

Это вопрос о Quickcheck в частности, или о случайности в целом? – Michael

+0

Поскольку 'Char' является экземпляром' Enum', вы можете написать 'letters = ['a' .. 'z']', чтобы избежать необходимости вводить все строчные буквы вручную. – chepner

ответ

7

Есть ли способ изменить Gen String к String?

Нет, решительно нет. По какой-то причине люди, приходящие с других языков программирования, всегда, кажется, думают, что «они оба типа типов типов, поэтому, безусловно, они могут быть конвертируемыми». Неа! Gen String - это нечто совершенно, принципиально отличное от String. Последний - просто простое значение данных - список символов. Но Gen String является генератором, действие, которое генерирует строки. Предполагая, что это можно преобразовать в строку, это похоже на то, что корова может быть преобразована в бутылку молока.

Правильная вещь для конечно, для getString также имеют Gen тип, потому что генерации строки является то, что он делает.

getString :: Int -> Gen String 

Вопрос заключается в том, как реализовать что. Ну, это догадки, потому что вы не указали, что именно Gen, но такие конструкторы типа в Haskell обычно applicative functors. Это позволяет писать

getString 0 = pure [] 
getString n = (:) <$> lowerAlpha <*> getString (n - 1) 

Как Gallais замечания, это также может быть записана короче

getString n = replicateM n lowerAlpha 
+1

Возможно, стоит упомянуть 'replicateM'. – gallais

3

Возможно, вы ищете vectorOf, то есть:

import Test.QuickCheck 

getString :: Int -> Gen String 
getString n = vectorOf n lowerAlpha 

Чтобы действительно генерировать случайную строку вы можете использовать generate (требуется IO-монада):

main = do 
    generate (getString 25) >>= putStrLn 

или просто из РЕПЛ GHCI:

ghci> generate (getString 25) 
"siebrxrlvuuxdvhqwcfykqwdc" 
ghci> generate (getString 3) 
"rcv" 
1

Спасибо за вашу помощь. Это то, что я придумал. Работает хорошо. str <- listOf (choose ('a','z'))

Смежные вопросы