IT練習ノート

IT関連で調べたこと(実際は嵌ったこと)を書いています。

HLintでよく指摘される内容

今作成しているライブラリでHLintを実行してみました。傾向としては、冗長なdoと冗長なカッコの指摘が多いようでした。

src/Database\SQLServer\Internal\Tokens.hs:626:1: Suggestion: Use newtype instead of data
Found:
  data ROW = ROW{columnValues :: [ColumnValue]}
               deriving (Show, Eq, Generic)
Why not:
  newtype ROW = ROW{columnValues :: [ColumnValue]}
                  deriving (Show, Eq, Generic)
Note: decreases laziness
src/Database\SQLServer\Internal\Types.hs:406:20: Warning: Use replicate
Found:
  take n $ repeat $ Bit.block Bit.bool
Why not:
  replicate n (Bit.block Bit.bool)
src/Database\SQLServer\ResultSet.hs:467:37: Suggestion: Avoid lambda
Found:
  \ row -> getRecord' meta row
Why not:
  getRecord' meta
src/Lib.hs:71:20: Suggestion: Use null
Found:
  length x == 0
Why not:
  null x
Note: increases laziness
src/Lib.hs:90:12: Suggestion: Move brackets to avoid $
Found:
  "[trace] [c] ====================> RCPRequest request " ++
    (show $ BS.length rcpreq)
Why not:
  "[trace] [c] ====================> RCPRequest request " ++
    show (BS.length rcpreq)
src/Lib.hs:127:3: Warning: Use maybe
Found:
  if isJust rawsql then
    example_execute_sql_raw socket $ fromJust rawsql else
    maybe
      (case rpc of
           Just (r, _) -> example_execute_rpc socket r
           Nothing -> error "invalid parameter")
      (example_execute_sql socket)
      file
Why not:
  maybe
    (maybe
       (case rpc of
            Just (r, _) -> example_execute_rpc socket r
            Nothing -> error "invalid parameter")
       (example_execute_sql socket)
       file)
    (example_execute_sql_raw socket)
    rawsql
src/Lib.hs:142:16: Suggestion: Redundant $
Found:
  runGet (MT.evalStateT resolveTokens []) $ batchRes
Why not:
  runGet (MT.evalStateT resolveTokens []) batchRes
src/Lib.hs:143:3: Warning: Use when
Found:
  if info then mapM_ (printToken) tokens else return ()
Why not:
  Control.Monad.when info $ mapM_ (printToken) tokens
src/Lib.hs:150:15: Warning: Redundant do
Found:
  do mapM_ (mapM_ putStrLn) $ getRecordList2Str rs
Why not:
  mapM_ (mapM_ putStrLn) $ getRecordList2Str rs
rc/Lib.hs:226:13: Suggestion: Use <$>
Found:
  MT.lift (get :: Get RETURNSTATUS) >>= return . TknreturnStatus
Why not:
  TknreturnStatus <$> MT.lift (get :: Get RETURNSTATUS)
src/Lib.hs:410:4: Suggestion: Redundant bracket
Found:
  "@foo" @@ (fromGregorian 1900 1 1)
Why not:
  "@foo" @@ fromGregorian 1900 1 
.\src\Lib.hs:483:54: Suggestion: Use section
Found:
  ((==) '=')
Why not:
  ('=' ==)
.\src\Lib.hs:516:1: Suggestion: Use camelCase
Found:
  exNullSql_variant = ...
Why not:
  exNullSqlVariant = ...

io-streamでストリームを変更する

Generatorを作る必要があります。

以下のようにしてしまうと、固定値を永遠に流すストリームになってしまいます。

badFunc :: InputStream Int -> IO (InputStream Int)
badFunc s = do
  v <- S.read s
  case v of
    Just x  -> makeInputStream $ return $ Just x
    Nothing -> makeInputStream $ return Nothin

io-stream sample 2

CoqからHaskellのコードを生成する

Extractionという機能を使うとできるらしい。Coqで証明してHaskellで動作させる感じなのか。

coq.inria.fr

単純な方の定義

Inductive FBB : Type :=
  | Foo
  | Bar
  | Buzz.

Require Extraction.
Extraction Language Haskell.
Extraction "C:\work\FBB.hs" FBB.
module FBB where

import qualified Prelude

data FBB =
   Foo
 | Bar
 | Buzz

偶数判定は以下のように変換される。

Fixpoint evenb (n:nat) : bool :=
  match n with
  | O => true
  | S O => false
  | S (S n') => evenb n'
  end.
module Evneb where

import qualified Prelude

data Bool =
   True
 | False

data Nat =
   O
 | S Nat

evenb :: Nat -> Bool
evenb n =
  case n of {
   O -> True;
   S n0 -> case n0 of {
            O -> False;
            S n' -> evenb n'}}