haskell-jp / questions #74

学習用途でしたら,ぜひ再帰版もがんばってみてください.(私なら,リストのリストを処理する再帰関数Aから,リストを処理する再帰関数Bを呼ぶ,みたいな方針にすると思います)
もう一点よろしいでしょうか?
haskellではリストを処理する関数とリストのリストを処理する関数は型を分けて考える必要があるのでしょうか?
たぶん、分けて考える必要はないですよ(意図してる範囲がわからないけど)
例えば、intのリストとリストのリストは同じように扱うことができるのでしょうか?
リストの中身がIntかリストかに関わらず,引数で受け取った関数に受け渡すなら(つまり要素に直接触れないなら),同じように扱えると思います.
なるほど、、ありがとうございます!!
思い出せました。うまくいかないのは extensibleパッケージのレコードをRecord of Functionsとして扱った場合でした。

{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE ExplicitNamespaces  #-}
{-# LANGUAGE LiberalTypeSynonyms #-}
{-# LANGUAGE OverloadedLabels    #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE TypeOperators       #-}

import           Data.Extensible (type (>:))
import qualified Data.Extensible as E

type DebugEnvFields m =
   '[ "print" >: (forall a. Show a => a -> m ())
    ]

type DebugEnv m = E.Record (DebugEnvFields m)
そして、いただいた回答から気づいたんですが、そうした場合でも print 関数相当のものを一旦 newtype でラップしてあげればいけるんですね。
この程度のボイラープレートなら許容できそう。

type DebugEnvFields m =
   '[ "print" >: Printer m
    ]

newtype Printer m = Printer (forall a. Show a => a -> m ())
誰も指摘してなかったので補足すると、 -Wall で警告を有効にしていれば、どのパターンを網羅していないのか教えてくれるので、参考にするとよいでしょう。
今回の場合 :point_down: のように教えてくれます。

listed.hs:10:1: warning: [-Wincomplete-patterns]
    Pattern match(es) are non-exhaustive
    In an equation for ‘secmap’:
        Patterns not matched:
            _ []
            _ ([]:_:_)
   |
10 | secmap f [[]]           = [[]]
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^...
@koto.chiba.none has joined the channel
Haskell 入門 第 9 章 にて HUnit が使われているのですが、これって hspec とどう違うんですか? Hackage を流し読みしたけどわかりませんでした。
HspecはHUnitのラッパーです。
HUnitのAPIを do で書けるようにした、というのがHspecなのです。
なるほど。ありがとうございました!
@furatsuki_fiskm has joined the channel
@hideaki.nishioka has joined the channel
@ysk.m24t has joined the channel
@8128jp has joined the channel
@inamiy has joined the channel
@nakayoshix has joined the channel
@user.ryo has joined the channel
@tyahhahha has joined the channel
@takato.h0rikosh1 has joined the channel
@yuki08281993 has joined the channel
@taka23131 has joined the channel
初心者質問で恐縮なのですが、 日本語(UTF8)を含んだ Vector (String, Int) みたいなデータをちゃんと日本語入りで出力するのはどうしたらいいんでしょうか。
タプルの第一要素だけ取り出して出力するのはできるんですが、全体を出力しようとして間に show を挟んだりすると文字列が数値表記になってしまいます。
あんまり速度が速くないのでアレですが https://github.com/haskell-jp/unicode-show を使うとかですね。あと、機能的に過剰でなければ http://hackage.haskell.org/package/pretty-simple も同じように日本語を正しく出力してくれます。
ありがとうございます。試してみます
Addr# -valued literal って各文字が <=0xFF である文字列リテラルに # を後置すれば良いんですよね? 特に、値としては改行コードを含めたくないがソースの読みやすさ上改行したいときには、 \ の 直後に改行をして、適切な数の空白文字のあと \ 、そしてその後に続きを書けばいいんですよね?
なんかそのつもりでコードを書いていたら Addr# 中に大量の \x20 が出現してひっどいバグが出てきたので…。
厄介なのは、同一のリテラルなのにそのリテラルが現れる状況によって挙動が異なったりしているように見えることです。AtCoder用のsnippetなので、必要になるたびプログラムに埋め込んで用いているのですが、snippet ファイルをそのままコンパイルしても \x20 は現れないのに、 埋め込んだファイルの方を解析すると \x20 がバグをひき起こしているように見えるんですよね…。
考えているのはこんなのです:
CPPが有効だと複数行文字列リテラルの挙動が変わるはずです。
それだ!
@baavv914 has joined the channel
surveyの結果、次の事実を確認しました。
• CPPが有効だと、行末の \ は改行文字と一緒に削除される(複数行 #define を可能にするための処理)。Haskellの複数行文字列はこのC preprocessのあと \ と改行文字があるのを見て字句解析されるため、次の行の開始から \ までが文字列に含まれてしまう。
• Haskellの複数行文字列は \ <newline> <whitespace>* \ ではなく \ <whitespace>+ \ なので、 \ の後に空白文字を挟めば大丈夫、と書いてるのをどこかで見ましたが手元環境では見事死亡。GCCなら大丈夫、と書いてあったから、手元環境がclang (MacOS Catalina)であるせいかもしれない。
行末のバックスラッシュを二重にしてはどうですか

{-# LANGUAGE CPP #-}
str = "foo \\
  \bar baz"
main = print str
「行末にスペースを入れるといいよ」と書いてあるのは https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/phases.html#cpp-and-string-gaps ですね。情報が古いのか……
やって見ました.確かにうまくいきますね.GCCだと
\ <newline> → empty
Clangだと
\ <non-newline-whitespace>* <newline> → empty
で処理されてるんでしょうか.どっちにしてもHaskell multiline stringはその処理が終わったあと
\ <whitespace>+ \ → empty
(newlineはいらない)で処理されるから,次行のインデントが0でもない限りはうまくいくと.なんだこのdirty hackは…
Emacsのsyntax highlighterがバグりそうで嫌だなあ…….
予測通り,
{-# LANGUAGE CPP #-}
str0 = "J'ai mal \\
\a tete"
str1 = "J'ai mal \\a tete"
main = print $ str0 == str1

→ True でした.ah…
@rebornwwp has joined the channel
こんにちは。代数的データ型のデータコンストラクタから何か別の値への写像を作ろうとして、以下のような方法を取りました。しかし`-- ****`で囲った部分がどうもボイラープレート感がします(?)、何か簡潔な方法はありますか?

(加えて、代数的データ型のデータコンストラクタの種類(コード中の`FruitKind`に当たる型)を指してどう呼べばいいのかいまいちわからず検索に苦戦しています。何かいい呼び名があったら教えてください。variantとかでしょうか)
単純にデータコンストラクタを表すデータ型を作りたいということではないでしょうか?幾つか方法はあります.

まず型安全でない方法として, Data インスタンスを使うという方法があります.

import Data.Data

data ConstrK a where
  ConstrK :: Data a => Constr -> ConstrK a
  deriving (Eq, Show)

instance Ord (ConstrK a) where
  compare (ConstrK x) (ConstrK y) = show x `compare` show y

toConstrK :: Data a => a -> ConstrK a
toConstrK x = ConstrK $ toConstr x

みたいな感じのデータ型を使うと,同じようなことができると思います.なお,コンストラクタの一覧は dataTypeConstrs $ dataTypeOf (undefined :: a) とかで取れます.
もう一つは,作るデータ型を工夫するという手があって,今流行の HKD を使うことで次のように定義できると思います:

import Data.Barbie

data FruitSkel f
  = Apple (f Int)
  | Orange (f String)
  | Banana (f Char)
  deriving (Generic, FunctorB, ConstraintsB)

deriving instance AllBF Show f FruitSkel => Show (FruitSkel f)
deriving instance AllBF Eq f FruitSkel => Eq   (FruitSkel f)
deriving instance AllBF Ord  f FruitSkel => Ord   (FruitSkel f)

type Fruit = FruitSkel Identity
type FruitK = FruitSkel (Const ())

toKind :: Fruit -> FruitK
toKind = bmap $ const $ Const ()
他にも Generic のインスタンスであれば data constructor の情報が載ってるのでそこから情報を抜き出して data family を作るような型クラスを定義する方法や, Template Haskell でデータ型を作る方法などはありますが,多分手軽なのは上の二つだと思いますね
ありがとうございます。HKDでやってみます
@nmjr31 has joined the channel
@egisatoshi has joined the channel
@las has joined the channel
cabal で Cabal file warning ***[email protected]:0: version with tags という警告が表示されるのですが、これってどういうことなんでしょうか? もしかして 0.1.0.0 とかではなく 0.1 とバージョンを設定しろってことですかね?
@amderbar has joined the channel
気になったのでやってみたのですが、手元では再現しませんでした。
どんなcabalファイルでどのバージョンのcabal-installを使ったら発生したんですか?