How to print integer literals in binary or hex in haskell?
printBinary 5 => "0101"
printHex 5 => "05"
Which libraries/functions allow this?
I came across the Numeric module and its showIntAtBase function but have been unable to use it correctly.
> :t showIntAtBase
showIntAtBase :: (Integral a) => a -> (Int -> Char) -> a -> String -> String
The Numeric module includes several functions for showing an Integral type at various bases, including showIntAtBase. Here are some examples of use:
import Numeric (showHex, showIntAtBase)
import Data.Char (intToDigit)
putStrLn $ showHex 12 "" -- prints "c"
putStrLn $ showIntAtBase 2 intToDigit 12 "" -- prints "1100"
You may also use printf of the printf package to format your output with c style format descriptors:
import Text.Printf
main = do
let i = 65535 :: Int
putStrLn $ printf "The value of %d in hex is: 0x%08x" i i
putStrLn $ printf "The html color code would be: #%06X" i
putStrLn $ printf "The value of %d in binary is: %b" i i
Output:
The value of 65535 in hex is: 0x0000ffff
The html color code would be: #00FFFF
The value of 65535 in binary is: 1111111111111111
If you import the Numeric and Data.Char modules, you can do this:
showIntAtBase 2 intToDigit 10 "" => "1010"
showIntAtBase 16 intToDigit 1023 "" => "3ff"
This will work for any bases up to 16, since this is all that intToDigit works for. The reason for the extra empty string argument in the examples above is that showIntAtBase returns a function of type ShowS, which will concatenate the display representation onto an existing string.
You can convert integer to binary with something like the following:
decToBin x = reverse $ decToBin' x
where
decToBin' 0 = []
decToBin' y = let (a,b) = quotRem y 2 in [b] ++ decToBin' a
usage in GHCi:
Prelude> decToBin 10
[1,0,1,0]
Hex can be written with 0x and binary with 0b prefix e.g.:
> 0xff
255
>:set -XBinaryLiterals
> 0b11
3
Note that binary requires the BinaryLiterals extension.
You could define your own recursive functions like:
import Data.Char (digitToInt)
import Data.Char (intToDigit)
-- generic function from base to decimal
toNum :: [Char] -> Int -> (Char -> Int) -> Int
toNum [] base map = 0
toNum s base map = base * toNum (init(s)) base map + map(last(s))
-- generic function from decimal to base k
toKBaseNum :: Int -> Int -> (Int -> Char) -> [Char]
toKBaseNum x base map | x < base = [map x]
| otherwise = toKBaseNum (x `div` base) base map ++ [map(x `mod` base)]
-- mapping function for hex to decimal
mapHexToDec :: Char -> Int
mapHexToDec x | x == 'A' = 10
| x == 'B' = 11
| x == 'C' = 12
| x == 'D' = 13
| x == 'E' = 14
| x == 'F' = 15
| otherwise = digitToInt(x) :: Int
-- map decimal to hex
mapDecToHex :: Int -> Char
mapDecToHex x | x < 10 = intToDigit(x)
| x == 10 = 'A'
| x == 11 = 'B'
| x == 12 = 'C'
| x == 13 = 'D'
| x == 14 = 'E'
| x == 15 = 'F'
-- hex to decimal
hexToDec :: String -> Int
hexToDec [] = 0
hexToDec s = toNum s 16 mapHexToDec
-- binary to decimal
binToDec :: String -> Int
binToDec [] = 0
binToDec s = toNum s 2 (\x -> if x == '0' then 0 else 1)
-- decimal to binary
decToBin :: Int -> String
decToBin x = toKBaseNum x 2 (\x -> if x == 1 then '1' else '0')
-- decimal to hex
decToHex :: Int -> String
decToHex x = toKBaseNum x 16 mapDecToHex
Explanation:
As you can see, the toNum function converts a k-based value to decimal, using the given base and a mapping function. The mapping function will map special characters to a decimal value (for ex. A=10, B=11, ... in hex). For binary mapping you could also use a lambda expression like you see in binToDec.
Whereas the toKBaseVal function is the opposite, converting a decimal to a k-based value. Again we need a mapping function which does the opposite: from a decimal to the corresponding special character of the k-based value.
As a test you can type:
binToDec(decToBin 7) = 7
Suppose you want to convert from decimal to octal:
-- decimal to octal
decToOct :: Int -> String
decToOct x = toKBaseNum x 8 (\x -> intToDigit(x))
Again, I use just a lambda expression, because the mapping is simple: just int to digit.
Hope that helps! Good programming!
Silly solution for one-liner fans:
(\d -> let fix f = let {x = f x} in x in fmap (\n -> "0123456789abcdef" !! n) (fix (\f l n -> if n == 0 then l :: [Int] else let (q, r) = quotRem n 16 in f (r:l) q) [] d)) 247
The nucleus of the one-liner is:
quotRem 247 16
For the sake of clarity, you can, alternatively, put the following in a file:
#!/usr/bin/env stack
{- stack script --resolver lts-12.1 -}
-- file: DecToHex.hs
module Main where
import System.Environment
fix :: (a -> a) -> a
fix f = let {x = f x} in x
ff :: ([Int] -> Int -> [Int]) -> [Int] -> Int -> [Int]
ff = \f l n ->
if n == 0
then l
else
let (q, r) = quotRem n 16
in f (r:l) q
decToHex :: Int -> String
decToHex d =
fmap (\n -> "0123456789abcdef" !! n)
(fix ff [] d)
main :: IO ()
main =
getArgs >>=
putStrLn . show . decToHex . read . head
And execute the script with:
stack runghc -- DecToHex.hs 247
I used fixed-point operator just so it is an example with fixed-point operator; also because it allowed me to construct the one-liner strictly bottom-up. (Note: bottom-up development is to be discouraged.)
References: stack script syntax, Command line arguments, fix operator definition.
recursion haskell hex haskell-stack
Here is a simple, efficient, base-agnostic, Unlicenced implementation:
convertToBase :: Word8 -> Integer -> String
convertToBase b n
| n < 0 = '-' : convertToBase b (-n)
| n < fromIntegral b = [(['0'..'9'] ++ ['A' .. 'Z']) !! fromIntegral n]
| otherwise = let (d, m) = n `divMod` fromIntegral b in convertToBase b d ++ convertToBase b m
You have to import Data.Word to use Word8 (which limits the values as much as reasonably possible), and you will often need fromIntegral (if only automatic type conversions were a thing...).
Using the FiniteBits class:
import Data.Bits (FiniteBits, finiteBitSize, testBit, shiftR)
showBits :: FiniteBits a => a -> String
showBits bits =
go (finiteBitSize bits - 1) where
go shift =
if shift >= 0
then
let bit = if testBit (shiftR bits shift) 0 then '1' else '0'
in bit : go (pred shift)
else
""
Examples:
showBits (4 :: Word8) => "00000100"
showBits (50 :: Int16) => "0000000000110010"
showBits (-127 :: Int32) => "11111111111111111111111110000001"
When working with text, I recommend using the text-show package which includes:
showbBin :: (Integral a, TextShow a) => a -> Builder
showbHex :: (Integral a, TextShow a) => a -> Builder
showbOct :: (Integral a, TextShow a) => a -> Builder
showbIntAtBase :: (Integral a, TextShow a) => a -> (Int -> Char) -> a -> Builder
For example, converting an Integer to Text in binary:
{-# LANGUAGE OverloadedStrings #-}
import TextShow (toText)
import TextShow.Data.Integral (showbBin)
toBinary :: Integer -> Text
toBinary n = toText . showbBin
> toBinary 6 == "110"
Perhaps you want to add a Text prefix. Builder allows you to efficiently construct Text; it is a monoid.
toBinaryWithPrefix :: Text -> Integer -> Text
toBinaryWithPrefix prefix n = toText $ fromText prefix <> showbBin n
For more information see the TextShow and TextShow.Data.Integral modules available on Hackage.
Related
I want to convert an enum into Int or vice verse, i.e. implement an bidirectional mapping between the tag of sum type and Int. I have tried fromEnum but it seems not fast enough, and then I tried unsafeCoerce but it doesn't works as expected:
import Data.Time.Clock
import Data.Int
import Unsafe.Coerce
import Control.Monad (replicateM_)
data Color = R | G | B
deriving (Enum)
main = do
printT 1 $ (unsafeCoerce R :: Int8)
printT 1000 $ (unsafeCoerce G :: Int8)
printT 1000000 $ (unsafeCoerce B :: Int8)
printT 1000000000 $ (unsafeCoerce R :: Int8)
printT 1 $ (fromEnum R)
printT 1000 $ (fromEnum G)
printT 1000000 $ (fromEnum B)
printT 1000000000 $ (fromEnum B)
---------- profile tools ------------
printT :: Show a => Int -> a -> IO ()
printT n x = print =<< timeIt n (pure x)
timeIt :: Int -> IO a -> IO a
timeIt n _ | n <= 0 = error "timeIt n | n <= 0"
timeIt n proc = do
t0 <- getCurrentTime
replicateM_ (n-1) proc
x <- proc
t1 <- getCurrentTime
putStrLn ("-- Time Used (repeat " ++ show n ++ " times): " ++ show (t1 `diffUTCTime` t0))
return x
So what is the fastest way to do this?
Is the Enum you actually care about your type, or someone else's? If it's someone else's, then you're not guaranteed any methods you can use besides fromEnum, so you're out of luck. If it's your own type, then you can reimplement it with a newtype and pattern synonyms instead of deriving, so that fromEnum is literally free (provided the compiler can specialize it wherever you use it):
{-# LANGUAGE PatternSynonyms #-}
module ColorEnum (Color(R,G,B)) where
import Data.Coerce (coerce)
newtype Color = UnsafeColor Int
pattern R, G, B :: Color
pattern R = UnsafeColor 0
pattern G = UnsafeColor 1
pattern B = UnsafeColor 2
maxColor :: Int
maxColor = 2
instance Enum Color where
succ (UnsafeColor a)
| a == maxColor = error "succ{Color}: tried to take `succ' of last tag in enumeration"
| otherwise = UnsafeColor (a + 1)
pred (UnsafeColor a)
| a == 0 = error "pred{Color}: tried to take `pred' of first tag in enumeration"
| otherwise = UnsafeColor (a - 1)
toEnum a
| a >= 0 && a <= maxColor = UnsafeColor a
| otherwise = error $ "toEnum{Color}: tag (" ++ show a ++ ") is outside of enumeration's range (0," ++ show maxColor ++ ")"
enumFrom (UnsafeColor a) = coerce [a..maxColor]
enumFromThen (UnsafeColor a) (UnsafeColor b) = coerce [a,b..if a > b then 0 else maxColor]
fromEnum = coerce
Caveats:
This is not an endorsement of how you did your benchmark (in fact, it probably is wrong, as commenters pointed out)
There's a good chance that things other than fromEnum will be made slower by this change
All of that code is just to replace data Color = R | G | B deriving (Enum)
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to make a type with restrictions
Is it possible in Haskell to create a type for example "Name" which is a String but containing no more then 10 letters?
If not how can I forbid to create a Person with to long name (where Person is defined like that: data Person = Person Name).
Maybe it is not important at all, maybe that kind of problems should be solved in Haskell in a different way?
Don't export the constructor from the module where you define the type, and instead export a “smart constructor”:
module Name (Name(), -- exports the type Name, but not the data constructor Name
nameFromString,
stringFromName)
where
data Name = Name String
-- this is the only way to create a Name
nameFromString :: String -> Maybe Name
nameFromString s | 10 < length s = Nothing
| otherwise = Just (Name s)
-- this is the only way to access the contents of a Name
stringFromName :: Name -> String
stringFromName (Name s) = s
So you're concerned that if you previously had code that didn't require names to be limited to ten characters, you can't just drop in nameFromString as it has type String -> Maybe Name instead of String -> Name.
First, if you really want to throw an exception, you can define
import Data.Maybe (fromMaybe)
nameFromString' :: String -> Name
nameFromString' = fromMaybe (error "attempted to construct an invalid Name") . nameFromString
and use that instead.
Second, throwing an exception is sometimes the wrong thing to do. Consider
askUserForName :: IO Name
askUserForName
= do putStr "What's your name? (10 chars max) "
s <- getLine
case nameFromString s of
Just n -> return n
Nothing -> askUserForName
Rewriting this to use exceptions would result in more complex code.
dave4420 has the answer for what you should do. That is, only export smart constructors. In a dependently typed language you could limit data types to certain forms. But, Haskell is not dependently typed.
Wait, no that is not true. Haskell is "the worlds most popular dependently typed language". You just have to fake the dependent types. Stop. Read no further if you are 1. still learning basic Haskell 2. not totally insane.
It is possible to encode your "no longer than 10 characters" constraint in the type system. with a type like
data Name where
Name :: LessThan10 len => DList Char len -> Name
but I'm getting ahead of myself
first of all, you need tons of extensions (I assume GHC 7.4, early versions can still do it, but it is much more of a pain)
{-# LANGUAGE TypeFamilies,
DataKinds,
GADTs,
FlexibleInstances,
FlexibleContexts,
ConstraintKinds-}
import Prelude hiding (succ)
now we build some machinery for type level naturals...using the new DataKinds extension
data Nat = Z | S Nat
type N1 = S Z --makes writing numbers easier
type N2 = S N1
--etc
type N10 = S N9
now we need a data representation of numbers and a way to generate them
data Natural n where
Zero :: Natural Z
Succ :: Natural a -> Natural (S a)
class Reify a where
reify :: a
instance Reify (Natural Z) where
reify = Zero
instance Reify (Natural n) => Reify (Natural (S n)) where
reify = Succ (reify)
okay, now we can encode the idea of number being less than 10, and write a helper to test it for boot
type family LTE (a :: Nat) (b :: Nat) :: Bool
type instance LTE Z b = True
type instance LTE (S a) Z = False
type instance LTE (S a) (S b) = LTE a b
--YAY constraint kinds!
type LessThan10 a = True ~ (LTE a N10)
data HBool b where
HTrue :: HBool True
HFalse :: HBool False
isLTE :: Natural a -> Natural b -> HBool (LTE a b)
isLTE Zero _ = HTrue
isLTE (Succ _) Zero = HFalse
isLTE (Succ a) (Succ b) = isLTE a b
with all of that we can define length encoded strings
data DList a len where
Nil :: DList a Z
Cons :: a -> DList a len -> DList a (S len)
toList :: DList a len -> [a]
toList Nil = []
toList (Cons x xs) = x:toList xs
data Name where
Name :: LessThan10 len => DList Char len -> Name
and even get the string back, and define a neat-oh Show instance for Name
nameToString :: Name -> String
nameToString (Name l) = toList l
instance Show Name where
show n = "Name: " ++ nameToString n
the problem is that we need a way to turn a String into a Name. That is harder.
First up, lets figure out how long a String is
data AnyNat where
AnyNat :: Natural n -> AnyNat
zero = AnyNat Zero
succ (AnyNat n) = AnyNat (Succ n)
lengthNat :: [a] -> AnyNat
lengthNat [] = zero
lengthNat (_:xs) = succ (lengthNat xs)
now it is a simple matter to turn lists into dependent lists
fromListLen :: Natural len -> [a] -> Maybe (DList a len)
fromListLen Zero [] = Just Nil
fromListLen Zero (x:xs) = Nothing
fromListLen (Succ a) [] = Nothing
fromListLen (Succ a) (x:xs) = do rs <- fromListLen a xs
return (Cons x rs)
still not home free, but we are getting there
data MaybeName b where
JustName :: LessThan10 len => DList Char len -> MaybeName True
NothingName :: MaybeName False
maybeName :: MaybeName b -> Maybe Name
maybeName (JustName l) = Just $ Name l
maybeName (NothingName) = Nothing
stringToName' :: Natural len -> String -> MaybeName (LTE len N10)
stringToName' len str = let t = isLTE len (reify :: Natural N10)
in case t of
HFalse -> NothingName
HTrue -> case fromListLen len str of
Just x -> JustName x
--Nothing -> logic error
the last bit just involves convincing GHC we are not trying to blow the compiler's brains out unsafePerformIO $ produce evilLaugh
stringToNameLen :: Natural len -> String -> Maybe Name
stringToNameLen len str = maybeName $ stringToName' len str
stringToNameAny :: AnyNat -> String -> Maybe Name
stringToNameAny (AnyNat len) str = stringToNameLen len str
stringToName :: String -> Maybe Name
stringToName str = stringToNameAny (lengthNat str) str
wow, I write long stack overflow posts, but this takes the cake
we test it
*Main> stringToName "Bob"
Just Name: Bob
*Main> stringToName "0123456789"
Just Name: 0123456789
*Main> stringToName "01234567890"
Nothing
So it works, and the type system now can enforce the invariant that your names are no more than 10 characters. Seriously though, odds are this is not worth your effort.
You described the type perfectly well. You'll soon regret it of course...
data Name = N1 Char
| N2 Char Char
| N3 Char Char Char
| N4 Char Char Char Char
| N5 Char Char Char Char Char
| N6 Char Char Char Char Char Char
| N7 Char Char Char Char Char Char Char
| N8 Char Char Char Char Char Char Char Char
| N9 Char Char Char Char Char Char Char Char Char
| N10 Char Char Char Char Char Char Char Char Char Char
deriving (Show, Eq,Ord)
prettyName :: Name -> String
prettyName (N1 a) = a:[]
prettyName (N2 a b) = a:b:[]
prettyName (N3 a b c) = a:b:c:[]
prettyName (N4 a b c d) = a:b:c:d:[]
prettyName (N5 a b c d e) = a:b:c:d:e:[]
prettyName (N6 a b c d e f) = a:b:c:d:e:f:[]
prettyName (N7 a b c d e f g) = a:b:c:d:e:f:g:[]
prettyName (N8 a b c d e f g h) = a:b:c:d:e:f:g:h:[]
prettyName (N9 a b c d e f g h i) = a:b:c:d:e:f:g:h:i:[]
prettyName (N10 a b c d e f g h i j) = a:b:c:d:e:f:g:h:i:j:[]
And while we're importing Text.PrettyPrint here in ghci, why not a parser?
import Text.ParserCombinators.Parsec
import Control.Applicative ((<*))
-- still lame
pN :: Parser Name
pN = do letters <- many1 alphaNum <* space
case letters of
a:[] -> return $ N1 a
a:b:[] -> return $ N2 a b
a:b:c:[] -> return $ N3 a b c
a:b:c:d:[] -> return $ N4 a b c d
a:b:c:d:e:[] -> return $ N5 a b c d e
a:b:c:d:e:f:[] -> return $ N6 a b c d e f
a:b:c:d:e:f:g:[] -> return $ N7 a b c d e f g
a:b:c:d:e:f:g:h:[] -> return $ N8 a b c d e f g h
a:b:c:d:e:f:g:h:i:[] -> return $ N9 a b c d e f g h i
a:b:c:d:e:f:g:h:i:j:[] -> return $ N10 a b c d e f g h i j
_ -> unexpected "excess of letters"
-- *Main> parseTest pN "Louise "
-- N6 'L' 'o' 'u' 'i' 's' 'e'
-- *Main> parseTest pN "Louisiana "
-- N9 'L' 'o' 'u' 'i' 's' 'i' 'a' 'n' 'a'
-- *Main> parseTest (fmap prettyName pN) "Louisiana "
-- "Louisiana"
-- *Main> parseTest pN "Mississippi "
-- parse error at (line 1, column 13):
-- unexpected excess of letters
... Maybe this wasn't such a good idea ...
Is there a difference between these two functions?
ghct says:
Prelude> :t (+1)
(+1) :: Num a => a -> a
Prelude> :t \x->x+1
\x->x+1 :: Num a => a -> a
But
When I used (+1) syntax in this piece of code:
data B = B {
pos :: Int,
cells :: [Int]
} deriving (Show)
createB :: Int -> B
createB n = B 0 (take n $ repeat 0)
size :: B -> Int
size b = length $ cells b
get_curr :: B -> Int
get_curr b = (cells b) !! (pos b)
apply :: (Int -> Int) -> B -> B
apply f b = let n = pos b
h = take n $ cells b -- head
t = drop (n + 1) $ cells b -- tail
in B n $ h ++ [f (get_curr b)] ++ t
-- ...
eval :: [Char] -> StateT B IO ()
eval [] = return ()
eval (x:xs) = do
b <- get
put $ case x of
'+' -> apply (+1) b
'-' -> apply (-1) b
'>' -> fwd b
'<' -> back b
otherwise -> b
-- ...
prelude (as well as compiler) said:
> :load BrainFuck.hs
[1 of 1] Compiling BrainFuck ( BrainFuck.hs, interpreted )
BrainFuck.hs:49:40:
No instance for (Num (Int -> Int))
arising from the literal `1'
Possible fix: add an instance declaration for (Num (Int -> Int))
In the expression: 1
In the first argument of `apply', namely `(- 1)'
In the expression: apply (- 1) b
Failed, modules loaded: none.
What am I doing wrong?
sorry if code is not-so-cool (full source here: https://github.com/nskeip/bf/blob/a755b2d27292593d63fe1e63c2a6e01cebc73520/BrainFuck.hs)
This code:
(-1)
... doesn't mean the same thing as this code:
\ x -> x - 1
- is a special case in Haskell; it is the only prefix operator in the language. When you write (-1), you get "negative one" which is a number, and not "subtract one" which is a function.
You should use subtract 1 to get what you need.
Your problem is not with (+1), it's with (-1):
Prelude> :t (-1)
(-1) :: Num a => a
-1 is a number! Try with apply (\x -> x-1) b or apply (subtract 1) b.
There is no difference between (+1) and \x -> x + 1 and if you look closely, (+1) isn't what's causing your error. (-1) is. And that's because unlike (+1), (-1) is not an operator section, it's negative one.
Instead of subtract the decrement expression can be written directly also as (+(-1)) .
dreiNplusEins :: Integer -> [Integer]
dreiNplusEins n = if n == 1 then [1] else if n `mod` 2 == 0 then
[n] ++ dreiNplusEins (n `div` 2)
else
[n] ++ dreiNplusEins (n * 3 + 1)
maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze,ObereGrenze,MaxZyklaenge)
maxZyklus m n = if m > n then (m,n,0) else if m == n then
(m,n,length(dreiNplusEins m))
else
(m,n,0)
type UntereGrenze = Integer
type ObereGrenze = Integer
type MaxZykLaenge = Integer
this is my program and this gives error as Not in scope: type constructor or class `MaxZyklaenge' how can i fix it ?
You have a typo in the type name:
In the type signature of maxZyklus you write MaxZyklaenge (lower case l), but in the type definition you write MayZykLaenge (capital L).
Even if you fix the typo you'll still get an error, since length returns an Int where you need an Integer. The following is one way to fix this (I've also rewritten your code to use guards):
import Data.List (genericLength)
dreiNplusEins :: Integer -> [Integer]
dreiNplusEins 1 = [1]
dreiNplusEins n
| n `mod` 2 == 0 = n : dreiNplusEins (n `div` 2)
| otherwise = n : dreiNplusEins (n * 3 + 1)
maxZyklus :: UntereGrenze -> ObereGrenze -> (UntereGrenze, ObereGrenze, MaxZyklaenge)
maxZyklus m n
| m == n = (m, n, genericLength $ dreiNplusEins m)
| otherwise = (m, n, 0)
type UntereGrenze = Integer
type ObereGrenze = Integer
type MaxZyklaenge = Integer
You could also use fromIntegral . length if you don't want the extra import, but I personally think genericLength is a little clearer.
Also, if you're interested, here's an arguably nicer way to write the first function:
dreiNplusEins :: Integer -> [Integer]
dreiNplusEins = (++[1]) . takeWhile (/=1) . iterate f
where
f n | even n = n `div` 2
| otherwise = n * 3 + 1
This just says "iteratively apply f until you hit a 1, and then tack a 1 on the end".
To find the number in a given range that produces the longest chain, you can use the following function:
longestBetween :: (Enum a, Integral b) => (a -> [b]) -> (a, a) -> (a, b)
longestBetween f (m, n)
= maximumBy (comparing snd)
. zip [m..n] $ map (genericLength . f) [m..n]
The first argument is the function that creates the list and the second is the range. The return value is a tuple containing the desired number in the range and the length of its list. Note that we need these additional imports:
import Data.List (genericLength, maximumBy)
import Data.Ord (comparing)
We can test as follows:
*Main> longestBetween dreiNplusEins (100, 1000)
(871,179)
Implementing the maxZyklus function you specify in the comments just takes a couple of minor changes at this point:
maxZyklus m n = (m, n, maximum $ map (genericLength . dreiNplusEins) [m..n])
maxZyklus 11 22 gives the desired (11, 22, 21).
Haskell is case sensitive.
In the type signature of maxZyklus:
... ,MaxZyklaenge)
-- # ^
But you have:
type MaxZykLaenge = Integer
-- # ^
It's defined as MaxZykLaenge (note the "L"), whereas you wrote the type as "MaxZyklaenge". Haskell is case-sensitive.
For project euler 59, I came up with this to return a list of tuples containing the decyphered string and the key used (and yes I know about Data.Bits):
module XOR where
import Data.List
import Data.Char
decToBin :: Integer -> [Integer]
decToBin x = reverse $ decToBin' x
where
decToBin' 0 = []
decToBin' y = let (a,b) = quotRem y 2 in [b] ++ decToBin' a
binToDec :: [Integer] -> Integer
binToDec xs = foldl (+) 0 $ map (\(x,y) -> x*(2^y) ) $reverse $ zip (reverse xs) [0..]
bitwise f x y = zipWith f x y
lenBin :: Integer -> Integer
lenBin x= length$ decToBin x
xor :: Integer -> Integer -> Bool
xor x y | x == y = 0
| x /= y = 1
| otherwise = error "Impossible"
bitwiseXOR :: Integer -> Integer -> Integer
bitwiseXOR a b | (lenBin a) > (lenBin b) = binToDec $ bitwise xor ((replicate ((lenBin a) - (lenBin b)) 0)++(decToBin b)) (decToBin a)
| (lenBin a) < (lenBin b) = binToDec $ bitwise xor ((replicate ((lenBin b) - (lenBin a)) 0)++(decToBin a)) (decToBin b)
| otherwise =binToDec $ bitwise xor (decToBin b) (decToBin a)
decyph :: [char] -> [char]
decyph key = map chr $ map (\(x,y)-> bitwiseXOR x (ord y) ) $ zip numbers $ cycle key
brute :: [([Char],[Char])]
brute = [(n,k)|k<- (sequence $ replicate 3 ['a'..'z']) ,n <- decyph k, "the" `isInfixOf` n]
numbers :: [Integer]
numbers = [79,59,12,2,79,35,8...]
The problem is that when I can't run decyph because the tuples it is producing only contain one character in the first part and the key in the second rather than the entire decrypted text with the key used. How can I fix this?
PS: Is it reasonable to assume the text will contain string "the"?
decyph key returns the deciphered text as a [Char]. With the syntax
n <- decyph k
in your list comprehension, n will be of type Char and be assigned the individual characters of the deciphered text, but what you want here is that it is assigned the full result of decyph so make it
let n = decyph k
Finally, check the type of elem:
> :t elem
elem :: (Eq a) => a -> [a] -> Bool
with the type of n being [Char], the first argument must be Char, but you have another string there. If you wish to work with elems, you could split up the deciphered text in words:
"the" `elem` words n
This will compile here then.
PS: Is it reasonable to assume the
text will contain string "the"?
It is most certainly a common English word, but the text could possibly be all-uppercase or the might only appear as The at the beginning of a sentence.