[英]Haskell rigid type variable error
我是Haskell初學者。 我想知道以下原因為何不起作用:
import System.Random
simulator :: (RandomGen g) => g -> Double -> (Bool, g)
simulator gen p = (x <= p, gen2)
where (x, gen2) = random gen :: (Double, g)
我得到的錯誤是:
• Couldn't match type ‘g’ with ‘g1’
‘g’ is a rigid type variable bound by
the type signature for:
simulator :: forall g. RandomGen g => g -> Double -> (Bool, g)
at simulate.hs:10:1-54
‘g1’ is a rigid type variable bound by
an expression type signature:
forall g1. (Double, g1)
at simulate.hs:12:37-47
Expected type: (Double, g1)
Actual type: (Double, g)
• In the expression: random gen :: (Double, g)
In a pattern binding: (x, gen2) = random gen :: (Double, g)
In an equation for ‘simulator’:
simulator gen p
= (x <= p, gen2)
where
(x, gen2) = random gen :: (Double, g)
• Relevant bindings include
gen :: g (bound at simulate.hs:11:11)
simulator :: g -> Double -> (Bool, g) (bound at simulate.hs:11:1)
where (x, gen2) = random gen :: (Double, g)
似乎Haskell無法匹配類型變量g
的單獨實例。 有什么線索嗎?
代碼的問題在最后一行,即帶有:: (Double, g)
類型注釋的代碼。 如所寫,您顯然希望該批注中的g
指向與您simulator
類型簽名中的g
相同的g
。 這是一個完全合理的期望,但是不幸的是,事實並非如此-默認情況下,兩個名稱相同的類型變量在不同的類型注釋中是不同的。 (這就是為什么在錯誤消息中,GHC將第二個g
隱式重命名為g1
。)
幸運的是,您可以解決此問題。 GHC帶有您可以打開的語言擴展,稱為ScopedTypeVariables
。 如果將{-# LANGUAGE ScopedTypeVariables #-}
到模塊頂部,則會啟用擴展。 但是,這仍然不能解決您的程序,因為ScopedTypeVariables
僅適用於使用forall
明確綁定的變量。 因此,你需要在兩個添加LANGUAGE
編譯和引入明確使用forall
:
{-# LANGUAGE ScopedTypeVariables #-}
import System.Random
simulator :: forall g. (RandomGen g) => g -> Double -> (Bool, g)
simulator gen p = (x <= p, gen2)
where (x, gen2) = random gen :: (Double, g)
這些咒語足以使GHC達到您最初的意圖。
就是說,如果您只是刪除第二個類型簽名並禁用ScopedTypeVariables
,則原始程序實際上也將編譯,因為GHC會根據使用方式為gen2
推斷合適的類型。 是否需要類型簽名是個人喜好,但是對於您確定確實需要簽名的情況或實際需要簽名的情況,了解發生的情況以及如何解決它仍然很有用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.