/ / Haskell型の一致エラー - haskell

ハスケル型マッチングエラー - haskell

私は次のようにいくつかの型同義語を定義しました:

type Potential = Float
type Label = String
type LabelSet = [String]

さらに、私は次の型と型シノニムを定義しました:

data VariableNode = VariableNode Label Potential LabelSet
type PGM = [VariableNode]

最後に、次の関数を使用してグラフを作成します。

makePGM :: [((Label, Potential), LabelSet)] -> PGM
makePGM (x:xs) = (VariableNode (fst . fst x) (snd . fst x) (snd x)) : makePGM xs
makePGM [] = []

上記の関数では、タプルのリストが提供されます。タプルの最初の要素は別のタプルであり、2番目のタプルは関数型シグネチャのとおりです。

私はハスケルに新しいので、次のエラーメッセージを解読する際にいくつかの問題があります。

Prelude> :l Graph.hs
[1 of 1] Compiling Graph            ( Graph.hs, interpreted )

Graph.hs:14:33: error:
• Couldn"t match type ‘a0 -> c0’ with ‘[Char]’
Expected type: Label
Actual type: a0 -> c0
• Probable cause: ‘(.)’ is applied to too few arguments
In the first argument of ‘VariableNode’, namely ‘(fst . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’
In the expression:
(VariableNode (fst . fst x) (snd . fst x) (snd x)) : makePGM xs

Graph.hs:14:39: error:
• Couldn"t match expected type ‘a0 -> (c0, b0)’
with actual type ‘(Label, Potential)’
• Possible cause: ‘fst’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘fst x’
In the first argument of ‘VariableNode’, namely ‘(fst . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’

Graph.hs:14:47: error:
• Couldn"t match type ‘a1 -> c1’ with ‘Float’
Expected type: Potential
Actual type: a1 -> c1
• Probable cause: ‘(.)’ is applied to too few arguments
In the second argument of ‘VariableNode’, namely ‘(snd . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’
In the expression:
(VariableNode (fst . fst x) (snd . fst x) (snd x)) : makePGM xs

Graph.hs:14:53: error:
• Couldn"t match expected type ‘a1 -> (a2, c1)’
with actual type ‘(Label, Potential)’
• Possible cause: ‘fst’ is applied to too many arguments
In the second argument of ‘(.)’, namely ‘fst x’
In the second argument of ‘VariableNode’, namely ‘(snd . fst x)’
In the first argument of ‘(:)’, namely
‘(VariableNode (fst . fst x) (snd . fst x) (snd x))’
Failed, modules loaded: none.

私はタイプミスマッチがあると結論づけましたが、私が定義したタイプと関数型シグネチャが与えられているので、どのようにそのようにはっきりしていません。

回答:

回答№1は2

問題はそれです f . g xf . (g x)。したがって、型は一致しません:

fst . fst ((1,2),3)
== fst . (fst ((1,2),3))
== fst . (1,2)
== ???? (.) expects a function, not a value

あなたはかっこを使うか fst . fst または $

-- reminder:
(.) :: (b -> c) -> (a -> b) -> a -> c
(.) f g x = f (g x)

($) :: (a -> b) -> a -> b
($) f x = f x

(fst . fst) x
== fst (fst  x)

fst $ fst x
== fst (fst x)

両方を組み合わせることもできます(例: fst . fst $ x、優先順位が $ 低い。


回答№2の場合は0

もちろん、これは実行するのに便利な練習です。このミスをした結果、演算子の優先順位と解析をHaskellでよりよく理解することを学んだのですが、一度経験が増えると、問題を回避でき、簡単なコードで終えることができます。呼び出しを構成する代わりにパターンマッチングを使用する fst そして snd

makePGM :: [((Label, Potential), LabelSet)] -> PGM
makePGM (((label, potential), set):xs) = VariableNode label potential set : makePGM xs
makePGM [] = []

コードは消費するデータのような形をしており、作業する値にわかりやすい名前を付けることができます。

もう一つの改善点は、この再帰パターンは非常に一般的です。リスト内の各アイテムに対して何かを行い、お互いに独立して、結果のリストを作成します。実際、それはまさに何ですか? map そうです。したがって、一度にこれらのPGM項目のうちの1つだけを扱う関数を記述してから、 map それらのリストで機能する関数に拡張する:

makePGM :: [((Label, Potential), LabelSet)] -> PGM
makePGM = map go
where go ((label, potential), set) = VariableNode label potential set