相关疑难解决方法(0)

类型检查器允许非常错误的类型替换,程序仍然编译

在尝试调试我的程序中的问题时(使用Gloss将2个具有相同半径的圆圈绘制成不同的大小),我偶然发现了一个奇怪的情况.在我处理对象的文件中,我有以下定义*:

type Coord = (Float,Float)
data Obj =  Player  { oPos :: Coord, oDims :: Coord }
Run Code Online (Sandbox Code Playgroud)

在导入Objects.hs的主文件中,我有以下定义:

startPlayer :: Obj
startPlayer = Player (0,0) 10
Run Code Online (Sandbox Code Playgroud)

发生这种情况是因为我为玩家添加和更改字段,并且忘记更新Player之后(其尺寸由单个数字确定以表示半径,但我将其更改为a startPlayer来表示(宽度,高度);如果我做的话玩家对象是一个非圆圈).

令人惊奇的是,上面的代码编译并运行,尽管第二个字段是错误的类型.

我首先想到的可能是我打开了不同版本的文件,但对编译程序中的任何文件的任何更改都会反映出来.

接下来我认为可能Coord由于某种原因没有被使用.注释会startPlayer产生编译器错误,甚至更奇怪的是,更改startPlayerin 10会导致适当的响应(更改起始大小startPlayer); 再次,尽管它是错误的类型.为了确保它正确读取数据定义,我在文件中插入了一个拼写错误,它给了我一个错误; 所以我正在查看正确的文件.

我试图粘贴2段以上的到自己的文件,并吐出预期误差的第二场PlayerPlayer是不正确.

什么可能允许这种情况发生?您认为这是Haskell的类型检查器应该阻止的事情.


我应该注意到,我原来的问题的答案,即两个被认为是相同半径的圆被绘制成不同的大小,其中一个半径实际上是负的.

haskell types

98
推荐指数
2
解决办法
3569
查看次数

Haskell进口有副作用吗?

我前段时间编写了一些代码,用于从十六进制编码的字符串文字OverloadedStrings创建ByteStrings,它使用提供的函数进行解码base16-bytestring.这工作得很好,但似乎我并没有像我想的那样理解它.

让我完全困惑的是这个.为什么

{-# LANGUAGE OverloadedStrings #-}

import Data.ByteString.Base16 ()
import qualified Data.ByteString as B

plaintext = "The message" :: B.ByteString

main = print plaintext
Run Code Online (Sandbox Code Playgroud)

编译并运行OK,但如果我删除导入Data.ByteString.Base16然后它无法编译(类似于这个问题):

test.hs:6:13:
No instance for (Data.String.IsString B.ByteString)
  arising from the literal `"The message"'
Run Code Online (Sandbox Code Playgroud)

根据Haskell Wiki,这样的导入"仅对导入类型类的实例很有用",但据我所知,base16-bytestring源代码没有定义任何类型类实例,只是encodedecode函数.

导入如何IsString为代码编译提供必要的实例?

haskell

24
推荐指数
1
解决办法
706
查看次数

是否可以拥有"本地"类型类实例?

我的意思是定义一个类型类的实例,它应用于函数的本地(letwhere)范围.更重要的是,我希望在这个实例中的函数是闭包,即能够关闭定义实例的词法范围中的变量(这意味着实例在下次调用它的函数时可能会有不同的工作方式).

我可以为您提供一个简化的用例.假设我有一个基于类型类操作的函数.在这个例子中,我使用平方,它可以在任何类型的实例上运行Num(是的,平方非常简单,可以很容易地重新实现,但它代表的是一些可能更复杂的东西).我需要能够按原样使用现有功能(无需更改或重新实现).

square :: Num a => a -> a
square x = x * x
Run Code Online (Sandbox Code Playgroud)

现在,假设我希望在模运算中使用此操作,即加法,乘法等等.这对于任何固定的模数基都很容易实现,但是我希望有一些通用的东西,我可以为不同的模数基重复使用.我希望能够定义这样的东西:

newtype ModN = ModN Integer deriving (Eq, Show)

-- computes (x * x) mod n
squareModN :: 
squareModN x n =
  let instance Num ModN where
    ModN x * ModN y = ModN ((x * y) `mod` n) -- modular multiplication
    _ + _ = undefined         -- the rest are unimplemented for simplicity
    negate _ = undefined …
Run Code Online (Sandbox Code Playgroud)

haskell typeclass

18
推荐指数
1
解决办法
1048
查看次数

打破Data.Set完整性而不使用GeneralizedNewtypeDeriving

下面的代码使用不安全的GeneralizedNewtypeDeriving扩展来Data.Set通过插入具有不同Ord实例的不同元素来中断:

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Data.Set
import System.Random

class AlaInt i where
  fromIntSet :: Set Integer -> Set i
  toIntSet :: Set i -> Set Integer
instance AlaInt Integer where
  fromIntSet = id
  toIntSet = id
newtype I = I Integer deriving (Eq, Show, AlaInt)
instance Ord I where compare (I n1) (I n2) = compare n2 n1 -- sic!  

insert' :: Integer -> Set Integer -> Set Integer
insert' n s = …
Run Code Online (Sandbox Code Playgroud)

security haskell type-safety language-extension

18
推荐指数
1
解决办法
703
查看次数

是否有任何语言扩展或Haskell的语言后代,有利于表达性,特别是在实例处理中?

有时候,我遇到了Haskell只匹配实例头的"特性",即

instance (a ~ NewDataTyp b) => C a
Run Code Online (Sandbox Code Playgroud)

现在将匹配任何类型,即C在程序中编写另一个实例声明将是一个错误,即使它不会因上下文而发生冲突a ~ NewDataTyp b.有时,需要付出很多努力才能克服; 我不得不重组数百行代码以避免这种限制.

是否有任何语言扩展或后代语言(Curry?Agda?)的设计具有更高的表现力优先级?这可能会牺牲(a)类型类世界的开放性(b)多项式时间类型检查.

编辑 - 对于那些对这个问题感兴趣的人,这个页面也许是有趣的:http://www.haskell.org/haskellwiki/Future_of_Haskell

haskell typeclass overlapping-instances

8
推荐指数
1
解决办法
287
查看次数

如何导入模块隐藏子模块或实例?

有了这个代码

import Control.Monad
import Control.Applicative
import Control.Monad.State

class DefVal a where
  defVal :: a

instance (DefVal a) => Alternative (Either a) where
  empty = Left defVal
  (Left _) <|> x = x
  x        <|> _ = x

instance (DefVal a) => MonadPlus (Either a) where
  mzero = empty
  mplus = (<|>)

newtype ErrString = ErrString { toString :: String }
  deriving Show

instance DefVal ErrString where
  defVal = ErrString "Default Error String"
Run Code Online (Sandbox Code Playgroud)

我收到错误消息:

Duplicate instance declarations:
  instance DefVal a => …
Run Code Online (Sandbox Code Playgroud)

import haskell module

4
推荐指数
1
解决办法
1225
查看次数

镜片生成应该像实例一样对待

我有另一个库中定义的数据类型.我想用Control.Lens库生成的镜头挂钩到该数据类型.

我是否需要在我的代码中使用newtype我的类型,或者认为已经定义的数据类型是否安全?

haskell lenses

3
推荐指数
1
解决办法
83
查看次数

在Scala中,为什么我不能实现像这样的普通泛型函数?

我想要一个名为"double"的泛型函数,其行为与此类似,可以应用于任何类型的def +(x:T):T方法:

double("A")
> "AA"
double(1)
> 2
double(0.2)
> 0.4
Run Code Online (Sandbox Code Playgroud)

所以我写这个函数是这样的:

def double[T](x:T):T = { x+x }
Run Code Online (Sandbox Code Playgroud)

但是当我在REPL中运行它时,scala会对此进行评估:

scala> def double[T](x:T):T = { x+x }
<console>:7: error: type mismatch;
 found   : T
 required: String
       def double[T](x:T):T = { x+x }
                                  ^
Run Code Online (Sandbox Code Playgroud)

我认为结构类型可能是实现duck typing的一种方法,我尝试过这样的东西,但它也不起作用:

def double[T <: { def +(x:T):T }](x:T):T = { x + x }
def double[T <: { def +[U<:T](x:U):U}](x:T) = { x + x }
Run Code Online (Sandbox Code Playgroud)

有没有人有这个想法?谢谢!


我发现在Haskell中,类似的函数可以像这样写:

double x = x + …
Run Code Online (Sandbox Code Playgroud)

generics functional-programming scala type-inference duck-typing

3
推荐指数
1
解决办法
704
查看次数

Haskell中不完整的隐式类型推断

让我们考虑以下示例:

data A = A{x::Int} deriving(Show)

instance Func_f (A -> String) where
    f _ = "ala"

class Func_f a where
    f :: a

main :: IO ()
main = do 
    let 
        a = A 5
        x = f a 
    print 5
Run Code Online (Sandbox Code Playgroud)

用.编译 ghc -XFlexibleInstances main.hs

(我试过了-XExtendedDefaultRules,但没有任何进展)

为什么在编译时会出现错误?:

main.hs:25:21:
    No instance for (Func_f (A -> t0)) arising from a use of `f'
    The type variable `t0' is ambiguous
    Possible fix: add a type signature that fixes these type variable(s) …
Run Code Online (Sandbox Code Playgroud)

haskell types overloading type-inference typeclass

2
推荐指数
1
解决办法
388
查看次数

键入类实例重新定义

  1. 我试图回答这个问题:"给定代数数据类型

    data Maybe a = Nothing | Just a
    
    Run Code Online (Sandbox Code Playgroud)

    选择正确的实例声明,显示类型构造函数Maybe是一个Monad."(取自这里:"DelftX:FP101x函数式编程简介".

  2. 我试图解决的方法是依次编译每个潜在的答案,例如,这个:

    instance Monad Maybe where
               return x = Just x
               Nothing >>= _ = Nothing
               (Just x ) >>= f = f x
    
    Run Code Online (Sandbox Code Playgroud)
  3. 我无法编译它,因为它已在前奏中定义.

    HwEx9.hs:16:10: error:
        Duplicate instance declarations:
          instance Monad Maybe -- Defined at HwEx9.hs:16:10
          instance Monad Maybe -- Defined in `GHC.Base'
    
    Run Code Online (Sandbox Code Playgroud)

我的问题是:我怎么编译它?

monads haskell instance duplicates redefinition

2
推荐指数
1
解决办法
132
查看次数