Send Beginners mailing list submissions to
        [email protected]

To subscribe or unsubscribe via the World Wide Web, visit
        http://www.haskell.org/mailman/listinfo/beginners
or, via email, send a message with subject or body 'help' to
        [email protected]

You can reach the person managing the list at
        [email protected]

When replying, please edit your Subject line so it is more specific
than "Re: Contents of Beginners digest..."


Today's Topics:

   1. Re:  Static records (CSV tables as modules) (Mark Fredrickson)
   2. Re:  Project euler question (Jacek Dudek)


----------------------------------------------------------------------

Message: 1
Date: Mon, 2 Jun 2014 11:28:43 -0500
From: Mark Fredrickson <[email protected]>
To: Ben Gamari <[email protected]>
Cc: [email protected]
Subject: Re: [Haskell-beginners] Static records (CSV tables as
        modules)
Message-ID:
        <CAOE7hBiMfY9D_ZdCLRMi-Tr4-1waqdMue=W46w5D=bfsiom...@mail.gmail.com>
Content-Type: text/plain; charset="utf-8"

Thanks for this solution. I think I could pair this with a data type
generated at runtime to index the vector and I'd be in great shape.

Related question: Does anyone know example code that creates data types at
runtime via TH?

-M



On Fri, May 30, 2014 at 6:40 PM, Ben Gamari <[email protected]> wrote:

> Mark Fredrickson <[email protected]> writes:
>
> > Hello,
> >
> > I writing a program that operates on some static data, currently saved in
> > CSV files. Right now I parse the files at run time and then generate
> > hashmap tables to connect the different data.
> >
> > Since I'm only ever operating on static data, I'm wondering if I can
> > generate module files that capture the records as a sum type. To access
> the
> > fields of the records, I could then imagine functions that exhaustively
> map
> > the constructors to the data.
> >
> > Do any tools to generate .hs files from CSV or other formats exist?
> Insofar
> > as this question has been asked before, the recommendation is "use
> Template
> > Haskell", which makes sense, but is a less complete solution than I'm
> > hoping for.
> >
> How does the TH hack below look?
>
> See this Gist for this code and a test-case. Unfortunately there are a
> few gotchas here,
>
>   1. The record type needs a `Lift` instance[2]. There are a pain to
>      write but can be derived[3]
>   2. The type of your data can't be defined in the same module as the TH
>      splice due to GHC's stage restriction
>
> Cheers,
>
> - Ben
>
>
> [1] https://gist.github.com/bgamari/efad8560ab7dd38e9407
> [2]
> http://hackage.haskell.org/package/template-haskell-2.9.0.0/docs/Language-Haskell-TH-Syntax.html#t:Lift
> [3] http://hackage.haskell.org/package/th-lift
>
>
> {-# LANGUAGE TemplateHaskell, FlexibleContexts #-}
>
> module StaticCSV (staticCSV) where
>
> import Control.Applicative
> import Data.Csv as Csv hiding (Name)
> import Data.Proxy
> import Data.Data
> import Language.Haskell.TH
> import Language.Haskell.TH.Syntax (Lift, lift)
> import qualified Data.ByteString.Lazy as BSL
> import qualified Data.Vector as V
>
> staticCSV :: (FromRecord a, Lift (V.Vector a)) => FilePath -> Proxy a ->
> ExpQ
> staticCSV fileName ty = do
>     contents <- runIO $ BSL.readFile fileName
>     csv <- case decode NoHeader contents of
>       Right a  -> return $ fmap (flip asProxyTypeOf ty) a
>       Left err -> fail err
>     [| csv |]
>
> instance Lift a => Lift (V.Vector a) where
>     lift v = do
>         list <- ListE <$> mapM lift (V.toList v)
>         return $ AppE (VarE 'V.fromList) list
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: 
<http://www.haskell.org/pipermail/beginners/attachments/20140602/aab4c921/attachment-0001.html>

------------------------------

Message: 2
Date: Mon, 2 Jun 2014 17:14:25 -0400
From: Jacek Dudek <[email protected]>
To: The Haskell-Beginners Mailing List - Discussion of primarily
        beginner-level topics related to Haskell <[email protected]>
Subject: Re: [Haskell-beginners] Project euler question
Message-ID:
        <cajxg2_egtk7-tvzhfncv3ah4fqttmck2af2_hh5qyq7rtn3...@mail.gmail.com>
Content-Type: text/plain; charset=UTF-8

{- Hi Martin, I must say, I don't follow your solution. Are you
generating all the permutations according to lexicographic order and
then choosing the one millionth one? Is there any particular reason
why you're using a monad? For what it's worth here's how I solved the
problem. -}

nthPerm :: Ord a => Int -> [a] -> Maybe [a]
-- This wrapper function just tests for cases
-- where the arguments don't make sense.

nthPerm m cs
    |  m < 1
    || null cs
    || product [1 .. length cs] < m
    || nub cs /= cs
        = Nothing
    | otherwise
        = Just (nthPerm' (m - 1) (sort cs))


nthPerm' :: Ord a => Int -> [a] -> [a]
-- This function calculates the solution for arguments that make sense.

-- Interpret the first argument as: the number of permutations, in
-- lexicographic order, that come BEFORE the one you want. So if you
-- wanted the 10-th permutation, the argument would be 9.

-- The second argument is the list of elements. It's assumed to be non
-- empty, contain no duplicates, and be sorted.

nthPerm' 0 cs = cs
nthPerm' m cs =
    let -- Number of elements that are permuted:
        n = length cs

        -- Number of permutations for lists with one element less than n:
        d = product [1 .. n - 1]

        -- Express m, the number of permutations before the one we want
        -- in this form: m = b * d + r, where 0 < r < d. This will tell
        -- us which "branch" our permutation is in. See "diagram" below.
        b = div m d
        r = rem m d

        -- Take out the element in the list that corresponds to the
        -- correct "branch".
        c = cs !! b

    in  -- The correct permutation = c : the correct sub-permutation
        -- of the original list with element c removed.
        c : nthPerm' r (delete c cs)


--      Diagram: The permutations of [0 .. 9] can be expressed as:
--
-- P [0 .. 9] =  map (0 :) $ P (delete 0 [0 .. 9])  -- branch 0
--            ++ map (1 :) $ P (delete 1 [0 .. 9])  -- branch 1
--            ++ map (2 :) $ P (delete 2 [0 .. 9])  -- branch 2
--                           .
--                           .
--                           .
--            ++ map (9 :) $ P (delete 9 [0 .. 9])  -- branch 9

On 5/22/14, martin <[email protected]> wrote:
> Am 05/21/2014 11:14 PM, schrieb David McBride:
>> Err actually I guess I got the euler answer, I guess I don't understand
>> your solution without the "minus" function
>> definition.
>
> "minus" is from Data.List.Ordered. It it like the standard set operation
> "minus" when both lists are ordered.
>
>>
>>
>> On Wed, May 21, 2014 at 5:10 PM, David McBride <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>>     For what it is worth, I'm getting the same answer as you are.
>>
>>     > head $ drop (1000000-1) $ sort $ Data.List.permutations [0..9]
>>     [2,7,8,3,9,1,5,4,6,0]
>>
>>     >(sort $ Data.List.permutations [0..9]) !! (1000000-1)
>>      [2,7,8,3,9,1,5,4,6,0]
>>
>>     I guess either euler is wrong or we are both crazy.
>>
>>
>>     On Wed, May 21, 2014 at 4:09 PM, martin <[email protected]
>> <mailto:[email protected]>> wrote:
>>
>>         Hello all,
>>
>>         I tried to solve Problem 24 (https://projecteuler.net/problem=24)
>> and came up with the following solution:
>>
>>         import Data.List.Ordered
>>         import Data.Char
>>
>>         elems = [0,1,2,3,4,5,6,7,8,9] :: [Int]
>>
>>         x = do
>>             a <- elems
>>             b <- elems `without` [a]
>>             c <- elems `without` [a,b]
>>             d <- elems `without` [a,b,c]
>>             e <- elems `without` [a,b,c,d]
>>             f <- elems `without` [a,b,c,d,e]
>>             g <- elems `without` [a,b,c,d,e,f]
>>             h <- elems `without` [a,b,c,d,e,f,g]
>>             i <- elems `without` [a,b,c,d,e,f,g,h]
>>             j <- elems `without` [a,b,c,d,e,f,g,h,i]
>>             return [a,b,c,d,e,f,g,h,i,j]
>>
>>         without a b = minus a ( sort b)
>>
>>         solution = filter isDigit $ show $ (x !! 1000001)
>>         -- "2783915640"
>>
>>         PE tells me that this is wrong, and I peeked the correct answer,
>> which is 2783915460 (the 4 and 6 are swapped). So I
>>         tried to find out where the correct answer is in my list x and
>> added
>>
>>         y = filter (\(x,y) -> x == "2783915460") $ zip (map (filter
>> isDigit . show) x) [1..]
>>         -- [("2783915460",1000000)]
>>
>>         How can that be? "solution" tells me that the millionth element is
>> "2783915640" but "y" tells me that
>>         "2783915460" is at
>>         the millionth position? I just cannot see it.
>>
>>         _______________________________________________
>>         Beginners mailing list
>>         [email protected] <mailto:[email protected]>
>>         http://www.haskell.org/mailman/listinfo/beginners
>>
>>
>>
>>
>>
>> _______________________________________________
>> Beginners mailing list
>> [email protected]
>> http://www.haskell.org/mailman/listinfo/beginners
>>
>
> _______________________________________________
> Beginners mailing list
> [email protected]
> http://www.haskell.org/mailman/listinfo/beginners
>


------------------------------

Subject: Digest Footer

_______________________________________________
Beginners mailing list
[email protected]
http://www.haskell.org/mailman/listinfo/beginners


------------------------------

End of Beginners Digest, Vol 72, Issue 2
****************************************

Reply via email to