我试图玩弄Haskell的类型,创建数据采取类型构造和具体类型(灵感来自这个).
这是我的kung.hs文件:
data Kung t a = Kung { field :: t a } deriving (Show, Eq)
val1 = Kung { field = [1,5] }
val2 = Kung { field = Just 3 }
--val3 = Kung { field = 3 }
Run Code Online (Sandbox Code Playgroud)
编译好并加载好:
*Main> :load C:\Test\Haskell\kung.hs
[1 of 1] Compiling Main ( C:\Test\Haskell\kung.hs, interpreted )
Ok, one module loaded.
*Main> val1
Kung {field = [1,5]}
*Main> val2
Kung {field = Just 3}
*Main>
Run Code Online (Sandbox Code Playgroud)
现在版本相同,但没有注释val3:
data Kung t a = Kung { field :: t a } deriving (Show, Eq)
val1 = Kung { field = [1,5] }
val2 = Kung { field = Just 3 }
val3 = Kung { field = 3 }
Run Code Online (Sandbox Code Playgroud)
这不编译:
*Main> :load C:\Test\Haskell\kung.hs
[1 of 1] Compiling Main ( C:\Test\Haskell\kung.hs, interpreted )
C:\Test\Haskell\kung.hs:7:24: error:
* No instance for (Num (t0 a0)) arising from the literal `3'
* In the `field' field of a record
In the expression: Kung {field = 3}
In an equation for `val3': val3 = Kung {field = 3}
|
7 | val3 = Kung { field = 3 }
| ^
Failed, no modules loaded.
Run Code Online (Sandbox Code Playgroud)
这似乎很好.没有办法从某种类型的构造函数和一些具体类型"分解"/"构造"(可能不是这里使用的正确术语)3类型的值Num.
回到GHCi解释器,加载没有val3注释的文件的第一个版本,然后:
Prelude> :load C:\Test\Haskell\kung.hs
[1 of 1] Compiling Main ( C:\Test\Haskell\kung.hs, interpreted )
Ok, one module loaded.
*Main> val3 = Kung { field = 3 }
*Main> :t val3
val3 :: Num (t a) => Kung t a
Run Code Online (Sandbox Code Playgroud)
我该怎么理解?为什么GHCi人为地"管理"分解3?(没有给出真实的类型)
那么这val3似乎并不可行:
*Main> val3
<interactive>:50:1: error:
* Ambiguous type variables `t0', `a0' arising from a use of `print'
prevents the constraint `(Show (t0 a0))' from being solved.
Probable fix: use a type annotation to specify what `t0', `a0' should be.
These potential instances exist:
instance (Show b, Show a) => Show (Either a b)
-- Defined in `Data.Either'
instance [safe] Show (t a) => Show (Kung t a)
-- Defined at C:\Test\Haskell\kung.hs:1:49
instance Show a => Show (Maybe a) -- Defined in `GHC.Show'
...plus 15 others
...plus one instance involving out-of-scope types
(use -fprint-potential-instances to see them all)
* In a stmt of an interactive GHCi command: print it
*Main>
Run Code Online (Sandbox Code Playgroud)
这里发生的微妙之处是什么?
这是工作中可怕的单态限制.以下编译正常:
data Kung t a = Kung { field :: t a } deriving (Show, Eq)
val3 :: Num (t a) => Kung t a
val3 = Kung { field = 3 }
Run Code Online (Sandbox Code Playgroud)
然而,单态限制阻止了GHC推断这个签名本身.相反,它试图找到一个单形类型.为此,它只有Haskell 默认规则可用.通常,这些暗示a Num-constrained类型变量是单态的Integer...但是整数不是形式t a,所以这会失败.
在正确的解决方法是,的确,自己写的类型签名,但你也可以关闭单态的限制:
{-# LANGUAGE NoMonomorphismRestriction #-}
data Kung t a = Kung { field :: t a } deriving (Show, Eq)
val3 = Kung { field = 3 }
Run Code Online (Sandbox Code Playgroud)
在GHCi中,单态限制是默认关闭的,因为GHC-7.8我相信它是.这就是为什么问题不会出现的原因.
| 归档时间: |
|
| 查看次数: |
125 次 |
| 最近记录: |