[英]haskell data definition error - Illegal literal in type (use -XDataKinds to enable)
我正在學習哈斯克爾。 我試過的時候:
Prelude> data Binary = 0 | 1
我有:
<interactive>:2:15:
Illegal literal in type (use -XDataKinds to enable): 0
即使我使用ghci -XDataKinds
啟動ghci
我還有:
<interactive>:2:15:
parse error in constructor in data/newtype declaration: 0
任何人都可以對此有所了解嗎?
基本上,不允許使用0和1之類的數字作為用戶定義類型的數據構造函數的名稱。 從語法上講,它們必須是以大寫字母開頭的單詞。 例如,您可以這樣做:
data Binary = O | I
(注意那些是大寫字母'o'和'i',而不是數字零和一。)
data Binary = 0 | 1
data Binary = 0 | 1
不是定義數據類型的正常形式。 data
定義需要數據構造函數 , 0
和1
不是它們的合法語法,因為它們已經被用於數值文字。 這是第二條錯誤消息試圖告訴您的,並且是基本的Haskell。 數據構造函數最常用的語法是大寫單詞,所以你可能想要更像的東西
data Binary = Zero | One
注意:此消息的其余部分是您可能不需要的高級內容,但我想解釋一下為什么您收到有關-XDataKinds
的第一條錯誤消息。
使用DataKinds
擴展, 0
和1
確實成為不同類型的合法“類型”(稱為Nat
,實際上“kind”是這里的技術術語),用於高級類型級編程,並且還有一些擴展,它是可以獲得包含它們的數據定義。
請注意,下面的示例可能不是很有用 ,我只是將它拼湊在一起以表明它是可行的。 在實踐中,除非你做的很高級,否則data Binary = Zero | One
data Binary = Zero | One
可能更像你想要的。
{-# LANGUAGE DataKinds, KindSignatures #-}
import GHC.TypeLits (Nat)
data Proxy (n :: Nat) = Proxy
data WeirdBinary = Zero (Proxy 0) | One (Proxy 1)
我實際上沒有能夠做的工作(雖然我只是嘗試了一會兒)是從data Binary = 0
。 我得到的最接近的是奇怪的東西
class (n :: Nat) /// a where
data Binary = (0 /// Bool) => ThisIsSilly
其中0
仍然需要在括號內。 我認為邏輯上這個特殊形式應該沒有括號,但事實並非如此。
鑒於此,我認為通過建議有一些方法可以使擴展在該位置適合0
,Haskell會不必要地混淆。 但是,由於解析和類型/種類檢查在GHC中是分開的階段,因此以更加用戶友好的方式捕獲它可能過於復雜,甚至可能最終意味着將來有效。
第一誤差是說,像文字值0
和1
(或實際上"foo"
, [1, 2, 3]
'Z'
)是無效的類型聲明的 。
您不能聲明包含現有類型元素的新類型,因為它看起來像您嘗試使用data Binday = 0 | 1
data Binday = 0 | 1
。 類型只能包含另一種類型的所有成員(這就是為什么在類型表達式中包含其他類型而不是值的原因 )。
DataKinds
擴展引入了新的類型形式(我不會在這里介紹),這意味着文字值可以出現在某些位置的類型聲明中。 因此它確實解決了“類型中的非法文字”錯誤,但即使使用DataKinds
在該位置仍然不允許使用文字值。
第二個錯誤告訴您編譯器無法解析“0”作為構造函數名稱。 構造函數必須以大寫字母1開頭,而0
顯然不是。
當我說“類型只能包含所有其他類型的成員”時,我早先撒了謊。 實際上新類型不能包含現有類型的任何成員; 它們包含不是任何現有類型成員的全新值。 這是通過要求構造函數標記新類型的所有值來實現的; 可能的構造函數在data
語句中聲明,並且它是必須在您寫入0
和1
的位置找到的構造函數的位置。
0
已經是現有類型Int
2的成員,因此無論您如何聲明它,它都不能成為新類型Binary
的成員。
你可以得到一個0
,它包含在 Binary
類型的Binary
:也許是ConstructorName 0
。 但是你必須將Binary
類型聲明為data Binary = ConstructorName Int | ...
data Binary = ConstructorName Int | ...
; 在類型聲明中的構造函數名稱之后應該出現類型,這些類型標識可以放置在新Binary
值的“槽”中的值的類型。 也沒有辦法讓“槽”只能包含0
或1
,它必須是整個類型。
1或者是作為中綴運算符的構造函數的冒號,但這里沒有相關性。
2實際上,文字表達式0
是重載的,因此它可以表示任何數字類型的零元素,但我所說的那個是Int
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.