Ответ 1
Строки - это действительно просто списки. Таким образом, вы можете преобразовать число, возвращаемое по длине, и добавить его в свою другую строку с обычными функциями списка:
print $ "length [1,2,3] " ++ show (length [1,2,3])
Я хочу написать код, который будет выводиться:
length [1,2,3] => 3
В Ruby я мог бы сделать это как:
puts "length [1,2,3] => #{[1,2,3].length}"
После попытки Haskell не удалось выполнить...
Prelude Data.List> print "length [1,2,3]"
"length [1,2,3]"
Prelude Data.List> print (length [1,2,3])
3
Prelude Data.List> print "length [1,2,3]" (length [1,2,3])
<interactive>:1:0:
Couldn't match expected type `Int -> t'
against inferred type `IO ()'
In the expression: print "length [1,2,3]" (length [1, 2, 3])
In the definition of `it':
it = print "length [1,2,3]" (length [1, 2, 3])
Prelude Data.List>
Строки - это действительно просто списки. Таким образом, вы можете преобразовать число, возвращаемое по длине, и добавить его в свою другую строку с обычными функциями списка:
print $ "length [1,2,3] " ++ show (length [1,2,3])
В то время как в других плакатах упоминаются многие "правильные" способы интерпретации строк, есть более удобный способ использования квазиковации и библиотека интерполированной строки-perl6:
{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}
import Text.InterpolatedString.Perl6 (qq)
main = putStrLn [$qq| length [1,2,3] => ${length [1,2,3]} |]
На самом деле существует также библиотека interpolatedstring-qq, которая предлагает синтаксис Ruby.
{-# LANGUAGE QuasiQuotes, ExtendedDefaultRules #-}
import Text.InterpolatedString.QQ (istr)
main = putStrLn [$istr| length [1,2,3] => #{length [1,2,3]} |]
Тем не менее, вы, вероятно, должны просто использовать show и ++ или concat для склеивания строк
main = putStrLn $ "length [1,2,3] => " ++ show (length [1,2,3])
или
main = putStrLn $ concat ["length [1,2,3] => ", show $ length (1,2,3)]
Последний имеет тенденцию выглядеть лучше, по коду, когда вы склеиваете много фрагментов строки.
Вы также можете просто использовать Text.Printf
, который включен в базовые библиотеки GHC:
> let format s = printf "length %s => %d\n" (show s) (length s)
> format [1,2,3]
length [1,2,3] => 3
В Hackage http://hackage.haskell.org существует несколько пакетов интерполяции строк, если вам нужны более благоприятные ситуации.
Используйте format функцию text-format-simple библиотека:
import Text.Format
format "length [1,2,3] => {0}" [show $ length [1,2,3]]
Попробуйте это в ghci:
Prelude> :t print
print :: (Show a) => a -> IO ()
Как вы можете видеть, функция print
принимает только один аргумент, а код выше - два.
Вместо этого попробуйте следующее:
putStrLn ("length [1,2,3] => " ++ show (length [1,2,3]))
Он соединяет две строки с ++
, а затем печатает ее.
Вы можете использовать что-то вроде
putStr "length [1,2,3] => "
print (length [1,2,3])
EDIT:
Если вы хотите сделать это как функцию, передать любой список и записать его длину, вы можете сделать это следующим образом:
print_length :: Show a => [a] -> IO ()
print_length xs = print ("length " ++ show xs ++ " => " ++ show (length xs))
Main> print_length [1,2,3,4,5]
"length [1,2,3,4,5] => 5"
Main> print_length []
"length [] => 0"
Конечно, как указано выше, вы можете использовать putStrLn
вместо печати.
В дополнение к тому, что другие сказали, вы также можете использовать оператор monadic bind >>
для объединения двух операций ввода-вывода:
putStr "length [1,2,3]: " >> print (length [1,2,3])
Это эквивалентно объединению их с do-notation:
do putStr "length [1,2,3]: "
print (length [1,2,3])
если вы просто хотите отлаживать такие вещи, как:
inc :: Int -> Int
inc x = [debug|1+x|]
inc 2
-- prints "1+x = 3"
-- returns 3
этот QuasiQuoter может помочь:
{-# LANGUAGE TemplateHaskell #-}
module Template where
import Language.Haskell.TH
import Language.Haskell.TH.Quote
import Language.Haskell.TH.Syntax
import Language.Haskell.Meta.Parse
import Debug.Trace
-- | e.g. f x = [debug|1+x|]
debug :: QuasiQuoter
debug = QuasiQuoter traceExp undefined undefined undefined
-- | e.g. traceExp "1+x" -> [| trace "1+x = $([|1+x|])" (1+x) |]
-- (or something)
traceExp :: String -> Q Exp
traceExp s = [|( trace $(showExp s) $(parseE s) )|]
-- | e.g. showExp "1+x" -> [| "1+x" ++ " = " ++ show (1+x) |]
showExp :: String -> Q Exp
showExp s = [|( $(stringE s) ++ " = " ++ show $(parseE s) )|]
-- | e.g. parseE "1+x" -> (UInfixE (LitE (IntegerL 1)) (VarE +) (VarE x))
parseE :: String -> Q Exp
parseE = return . either (const undefined) id . parseExp
-- $ cabal install haskell-src-exts
-- $ cabal install haskell-src-meta
переменные захватываются динамически. Я написал это, изучая Template Haskell, но debug
работает для отладки материала во время разработки.
Недавно я опубликовал fmt
библиотеку форматирования в моем ответе на другой вопрос. С помощью этой библиотеки вы можете написать интерполяцию следующим образом:
> "There are "+|n|+" million bicycles in "+|city|+"."
Хотя, вас также может заинтересовать какая-то библиотека TH с Quasi Quoters:
https://hackage.haskell.org/package/interpolate-0.1.1/docs/Data-String-Interpolate.html
Хотя, эта библиотека очень медленная по сравнению с fmt
.